1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-transport-debug.c In-proc debug subclass of DBusTransport
4 * Copyright (C) 2003 CodeFactory AB
5 * Copyright (C) 2003 Red Hat, Inc.
7 * Licensed under the Academic Free License version 1.2
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 #include "dbus-internals.h"
26 #include "dbus-connection-internal.h"
27 #include "dbus-transport-protected.h"
28 #include "dbus-transport-debug.h"
29 #include "dbus-server-debug.h"
30 #include "dbus-list.h"
32 #ifdef DBUS_BUILD_TESTS
35 * @defgroup DBusTransportDebug DBusTransportDebug
36 * @ingroup DBusInternals
37 * @brief In-process debug transport used in unit tests.
39 * Types and functions related to DBusTransportDebug.
40 * This is used for unit testing.
46 * Default timeout interval when reading or writing.
48 #define DEFAULT_INTERVAL 1
51 * Hack due to lack of OOM handling in a couple places.
52 * Need to alloc timeout permanently and enabled/disable so
53 * that check_timeout won't fail in messages_pending
55 #define WAIT_FOR_MEMORY() _dbus_sleep_milliseconds (250)
57 static dbus_bool_t check_timeout (DBusTransport *transport);
60 * Opaque object representing a debug transport.
63 typedef struct DBusTransportDebug DBusTransportDebug;
66 * Implementation details of DBusTransportDebug. All members are private.
68 struct DBusTransportDebug
70 DBusTransport base; /**< Parent instance */
72 DBusTimeout *timeout; /**< Timeout for moving messages. */
74 DBusTransport *other_end; /**< The transport that this transport is connected to. */
76 unsigned int timeout_added : 1; /**< Whether timeout has been added */
79 /* move messages in both directions */
81 move_messages (DBusTransport *transport)
83 DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport;
85 if (transport->disconnected)
88 while (!transport->disconnected &&
89 _dbus_connection_have_messages_to_send (transport->connection))
91 DBusMessage *message, *copy;
93 message = _dbus_connection_get_message_to_send (transport->connection);
94 _dbus_assert (message != NULL);
96 copy = dbus_message_copy (message);
100 _dbus_message_lock (message);
102 _dbus_connection_message_sent (transport->connection,
105 _dbus_verbose (" -->transporting message %s from %s %p to %s %p\n",
106 dbus_message_get_name (copy),
107 transport->is_server ? "server" : "client",
108 transport->connection,
109 debug_transport->other_end->is_server ? "server" : "client",
110 debug_transport->other_end->connection);
112 _dbus_connection_queue_received_message (debug_transport->other_end->connection,
114 dbus_message_unref (copy);
117 if (debug_transport->other_end &&
118 !debug_transport->other_end->disconnected &&
119 _dbus_connection_have_messages_to_send (debug_transport->other_end->connection))
121 if (!move_messages (debug_transport->other_end))
129 timeout_handler (void *data)
131 DBusTransport *transport = data;
133 if (!move_messages (transport))
136 if (!check_timeout (transport))
143 check_timeout (DBusTransport *transport)
145 DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport;
147 if (transport->connection &&
148 transport->authenticated &&
149 (transport->messages_need_sending ||
150 (debug_transport->other_end &&
151 debug_transport->other_end->messages_need_sending)))
153 if (!debug_transport->timeout_added)
155 /* FIXME this can be fixed now, by enabling/disabling
156 * the timeout instead of adding it here
158 if (!_dbus_connection_add_timeout (transport->connection,
159 debug_transport->timeout))
161 debug_transport->timeout_added = TRUE;
166 if (debug_transport->timeout_added)
168 _dbus_connection_remove_timeout (transport->connection,
169 debug_transport->timeout);
170 debug_transport->timeout_added = FALSE;
178 debug_finalize (DBusTransport *transport)
180 DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport;
182 if (debug_transport->timeout_added)
183 _dbus_connection_remove_timeout (transport->connection,
184 debug_transport->timeout);
186 if (debug_transport->other_end)
188 _dbus_transport_disconnect (debug_transport->other_end);
189 debug_transport->other_end = NULL;
192 _dbus_transport_finalize_base (transport);
194 _dbus_timeout_unref (debug_transport->timeout);
196 dbus_free (transport);
200 debug_handle_watch (DBusTransport *transport,
208 debug_disconnect (DBusTransport *transport)
213 debug_connection_set (DBusTransport *transport)
215 if (!check_timeout (transport))
221 debug_messages_pending (DBusTransport *transport,
222 int messages_pending)
224 while (!check_timeout (transport))
229 debug_do_iteration (DBusTransport *transport,
231 int timeout_milliseconds)
233 move_messages (transport);
237 debug_live_messages_changed (DBusTransport *transport)
241 static DBusTransportVTable debug_vtable = {
245 debug_connection_set,
246 debug_messages_pending,
248 debug_live_messages_changed
252 create_timeout_object (DBusTransportDebug *debug_transport)
254 debug_transport->timeout = _dbus_timeout_new (DEFAULT_INTERVAL,
256 debug_transport, NULL);
258 return debug_transport->timeout != NULL;
262 * Creates a new debug server transport.
264 * @param client the client transport that the server transport
266 * @returns a new debug transport
269 _dbus_transport_debug_server_new (DBusTransport *client)
271 DBusTransportDebug *debug_transport;
273 debug_transport = dbus_new0 (DBusTransportDebug, 1);
275 if (debug_transport == NULL)
278 if (!_dbus_transport_init_base (&debug_transport->base,
282 dbus_free (debug_transport);
286 if (!create_timeout_object (debug_transport))
288 _dbus_transport_finalize_base (&debug_transport->base);
289 dbus_free (debug_transport);
293 debug_transport->base.authenticated = TRUE;
295 /* Connect the two transports */
296 debug_transport->other_end = client;
297 ((DBusTransportDebug *)client)->other_end = (DBusTransport *)debug_transport;
299 _dbus_verbose (" new debug server transport %p created, other end %p\n",
300 debug_transport, debug_transport->other_end);
302 return (DBusTransport *)debug_transport;
306 * Creates a new debug client transport.
308 * @param server_name name of the server transport that
309 * the client should try to connect to.
310 * @param error address where an error can be returned.
311 * @returns a new transport, or #NULL on failure.
314 _dbus_transport_debug_client_new (const char *server_name,
317 DBusServer *debug_server;
318 DBusTransportDebug *debug_transport;
321 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
323 debug_server = _dbus_server_debug_lookup (server_name);
327 dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
331 if (!_dbus_string_init (&address, _DBUS_INT_MAX))
333 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
337 if (!_dbus_string_append (&address, "debug-pipe:name=") ||
338 !_dbus_string_append (&address, server_name))
340 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
341 _dbus_string_free (&address);
345 debug_transport = dbus_new0 (DBusTransportDebug, 1);
346 if (debug_transport == NULL)
348 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
349 _dbus_string_free (&address);
353 if (!_dbus_transport_init_base (&debug_transport->base,
357 dbus_free (debug_transport);
358 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
359 _dbus_string_free (&address);
363 _dbus_string_free (&address);
365 if (!create_timeout_object (debug_transport))
367 _dbus_transport_finalize_base (&debug_transport->base);
368 dbus_free (debug_transport);
369 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
373 if (!_dbus_server_debug_accept_transport (debug_server,
374 (DBusTransport *)debug_transport))
376 _dbus_timeout_unref (debug_transport->timeout);
377 _dbus_transport_finalize_base (&debug_transport->base);
378 dbus_free (debug_transport);
379 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
383 /* FIXME: Prolly wrong to do this. */
384 debug_transport->base.authenticated = TRUE;
386 _dbus_verbose (" new debug client transport %p created, other end %p\n",
387 debug_transport, debug_transport->other_end);
389 return (DBusTransport *)debug_transport;
394 #endif /* DBUS_BUILD_TESTS */