2003-01-30 Anders Carlsson <andersca@codefactory.se>
[platform/upstream/dbus.git] / dbus / dbus-transport-debug.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-transport-debug.c In-proc debug subclass of DBusTransport
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-connection-internal.h"
26 #include "dbus-transport-protected.h"
27 #include "dbus-transport-debug.h"
28 #include "dbus-server-debug.h"
29 #include "dbus-list.h"
30
31 #ifdef DBUS_BUILD_TESTS
32
33 /**
34  * @defgroup DBusTransportDebug DBusTransportDebug
35  * @ingroup  DBusInternals
36  * @brief In-process debug transport used in unit tests.
37  *
38  * Types and functions related to DBusTransportDebug.
39  * This is used for unit testing.
40  *
41  * @{
42  */
43
44 /**
45  * Default timeout interval when reading or writing.
46  */
47 #define DEFAULT_INTERVAL 10
48
49 /**
50  * Opaque object representing a debug transport.
51  *
52  */
53 typedef struct DBusTransportDebug DBusTransportDebug;
54
55 /**
56  * Implementation details of DBusTransportDebug. All members are private.
57  */
58 struct DBusTransportDebug
59 {
60   DBusTransport base;                   /**< Parent instance */
61
62   DBusTimeout *write_timeout;           /**< Timeout for reading. */
63   DBusTimeout *read_timeout;            /**< Timeout for writing. */
64   
65   DBusTransport *other_end;             /**< The transport that this transport is connected to. */
66 };
67
68 static void
69 debug_finalize (DBusTransport *transport)
70 {
71   _dbus_transport_finalize_base (transport);  
72
73   dbus_free (transport);
74 }
75
76 static void
77 do_reading (DBusTransport *transport)
78 {
79   if (transport->disconnected)
80     return;
81
82   /* Now dispatch the messages */
83   while (dbus_connection_dispatch_message (transport->connection));
84 }
85
86 static void
87 check_read_timeout (DBusTransport *transport)
88 {
89   DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport;
90   dbus_bool_t need_read_timeout;
91
92   if (transport->connection == NULL)
93     return;
94
95   _dbus_transport_ref (transport);
96   
97   need_read_timeout = dbus_connection_get_n_messages (transport->connection) > 0;
98   
99   if (transport->disconnected)
100     need_read_timeout = FALSE;
101   
102   if (need_read_timeout &&
103       debug_transport->read_timeout == NULL)
104     {
105       debug_transport->read_timeout =
106         _dbus_timeout_new (DEFAULT_INTERVAL, (DBusTimeoutHandler)do_reading,
107                            transport, NULL);
108
109       if (debug_transport->read_timeout == NULL)
110         goto out;
111
112       if (!_dbus_connection_add_timeout (transport->connection,
113                                          debug_transport->read_timeout))
114         {
115           _dbus_timeout_unref (debug_transport->read_timeout);
116           debug_transport->read_timeout = NULL;
117
118           goto out;
119         }
120     }
121   else if (!need_read_timeout &&
122            debug_transport->read_timeout != NULL)
123     {
124       _dbus_connection_remove_timeout (transport->connection,
125                                        debug_transport->read_timeout);
126       _dbus_timeout_unref (debug_transport->read_timeout);
127       debug_transport->read_timeout = NULL;
128     }
129
130  out:
131   _dbus_transport_unref (transport);      
132 }
133
134 static void
135 do_writing (DBusTransport *transport)
136 {
137   if (transport->disconnected)
138     return;
139
140   while (!transport->disconnected &&
141          _dbus_connection_have_messages_to_send (transport->connection))
142     {
143       DBusMessage *message, *copy;
144       
145       message = _dbus_connection_get_message_to_send (transport->connection);
146       _dbus_message_lock (message);
147       
148       copy = dbus_message_new_from_message (message);
149       
150       _dbus_connection_message_sent (transport->connection,
151                                      message);
152       
153       _dbus_connection_queue_received_message (((DBusTransportDebug *)transport)->other_end->connection,
154                                                copy);
155       dbus_message_unref (copy);
156     }
157
158   check_read_timeout (((DBusTransportDebug *)transport)->other_end);
159 }
160
161 static void
162 check_write_timeout (DBusTransport *transport)
163 {
164   DBusTransportDebug *debug_transport = (DBusTransportDebug *)transport;
165   dbus_bool_t need_write_timeout;
166   
167   if (transport->connection == NULL)
168     return;
169
170   _dbus_transport_ref (transport);
171
172   need_write_timeout = transport->messages_need_sending;
173   
174   if (transport->disconnected)
175     need_write_timeout = FALSE;
176
177   if (need_write_timeout &&
178       debug_transport->write_timeout == NULL)
179     {
180       debug_transport->write_timeout =
181         _dbus_timeout_new (DEFAULT_INTERVAL, (DBusTimeoutHandler)do_writing,
182                            transport, NULL);
183
184       if (debug_transport->write_timeout == NULL)
185         goto out;
186
187       if (!_dbus_connection_add_timeout (transport->connection,
188                                          debug_transport->write_timeout))
189         {
190           _dbus_timeout_unref (debug_transport->write_timeout);
191           debug_transport->write_timeout = NULL;
192         }
193     }
194   else if (!need_write_timeout &&
195            debug_transport->write_timeout != NULL)
196     {
197       _dbus_connection_remove_timeout (transport->connection,
198                                        debug_transport->write_timeout);
199       _dbus_timeout_unref (debug_transport->write_timeout);
200       debug_transport->write_timeout = NULL;
201     }
202
203  out:
204   _dbus_transport_unref (transport);
205 }
206
207 static void
208 debug_handle_watch (DBusTransport *transport,
209                     DBusWatch     *watch,
210                     unsigned int   flags)
211 {
212 }
213
214 static void
215 debug_disconnect (DBusTransport *transport)
216 {
217 }
218
219 static void
220 debug_connection_set (DBusTransport *transport)
221 {
222 }
223
224 static void
225 debug_messages_pending (DBusTransport *transport,
226                         int            messages_pending)
227 {
228   check_write_timeout (transport);
229 }
230
231 static void
232 debug_do_iteration (DBusTransport *transport,
233                     unsigned int   flags,
234                     int            timeout_milliseconds)
235 {
236 }
237
238 static void
239 debug_live_messages_changed (DBusTransport *transport)
240 {
241 }
242
243 static DBusTransportVTable debug_vtable = {
244   debug_finalize,
245   debug_handle_watch,
246   debug_disconnect,
247   debug_connection_set,
248   debug_messages_pending,
249   debug_do_iteration,
250   debug_live_messages_changed
251 };
252
253 /**
254  * Creates a new debug server transport.
255  *
256  * @param client the client transport that the server transport
257  * should use.
258  * @returns a new debug transport
259  */
260 DBusTransport*
261 _dbus_transport_debug_server_new (DBusTransport *client)
262 {
263   DBusTransportDebug *debug_transport;
264
265   debug_transport = dbus_new0 (DBusTransportDebug, 1);
266   
267   if (debug_transport == NULL)
268     return NULL;
269
270   if (!_dbus_transport_init_base (&debug_transport->base,
271                                   &debug_vtable,
272                                   TRUE))
273     {
274       dbus_free (debug_transport);
275       return NULL;
276     }
277
278   debug_transport->base.authenticated = TRUE;
279
280   /* Connect the two transports */
281   debug_transport->other_end = client;
282   ((DBusTransportDebug *)client)->other_end = (DBusTransport *)debug_transport;
283   
284   return (DBusTransport *)debug_transport;
285 }
286
287 /**
288  * Creates a new debug client transport.
289  *
290  * @param server_name name of the server transport that
291  * the client should try to connect to.
292  * @param result address where a result code can be returned.
293  * @returns a new transport, or #NULL on failure. 
294  */
295 DBusTransport*
296 _dbus_transport_debug_client_new (const char     *server_name,
297                                   DBusResultCode *result)
298 {
299   DBusServer *debug_server;
300   DBusTransportDebug *debug_transport;
301   
302   debug_server = _dbus_server_debug_lookup (server_name);
303
304   if (!debug_server)
305     {
306       dbus_set_result (result, DBUS_RESULT_NO_SERVER);
307       return NULL;
308     }
309
310   debug_transport = dbus_new0 (DBusTransportDebug, 1);
311   if (debug_transport == NULL)
312     {
313       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
314       return NULL;
315     }
316
317   if (!_dbus_transport_init_base (&debug_transport->base,
318                                   &debug_vtable,
319                                   FALSE))
320     {
321       dbus_free (debug_transport);
322       dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
323       return NULL;
324     }
325
326   if (!_dbus_server_debug_accept_transport (debug_server, (DBusTransport *)debug_transport))
327     {
328       _dbus_transport_finalize_base (&debug_transport->base);
329
330       dbus_free (debug_transport);      
331       dbus_set_result (result, DBUS_RESULT_IO_ERROR);
332       return NULL;
333       
334     }
335
336   /* FIXME: Prolly wrong to do this. */
337   debug_transport->base.authenticated = TRUE;
338   
339   return (DBusTransport *)debug_transport;
340 }
341
342 /** @} */
343
344 #endif /* DBUS_BUILD_TESTS */