/* dbus-transport-debug.c In-proc debug subclass of DBusTransport
*
* Copyright (C) 2003 CodeFactory AB
+ * Copyright (C) 2003 Red Hat, Inc.
*
* Licensed under the Academic Free License version 1.2
*
/**
* Default timeout interval when reading or writing.
*/
-#define DEFAULT_INTERVAL 10
+#define DEFAULT_INTERVAL 1
+
+/**
+ * Hack due to lack of OOM handling in a couple places.
+ * Need to alloc timeout permanently and enabled/disable so
+ * that check_timeout won't fail in messages_pending
+ */
+#define WAIT_FOR_MEMORY() _dbus_sleep_milliseconds (250)
+
+static dbus_bool_t check_timeout (DBusTransport *transport);
/**
* Opaque object representing a debug transport.
{
DBusTransport base; /**< Parent instance */
- DBusTimeout *write_timeout; /**< Timeout for reading. */
- DBusTimeout *read_timeout; /**< Timeout for writing. */
+ DBusTimeout *timeout; /**< Timeout for moving messages. */
DBusTransport *other_end; /**< The transport that this transport is connected to. */
-};
-
-static void
-debug_finalize (DBusTransport *transport)
-{
- _dbus_transport_finalize_base (transport);
-
- dbus_free (transport);
-}
-static void
-do_reading (DBusTransport *transport)
-{
- DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport;
-
- if (transport->disconnected)
- return;
-
- /* Now dispatch the messages */
- if (dbus_connection_dispatch_message (transport->connection))
- {
- debug_transport->read_timeout =
- _dbus_timeout_new (DEFAULT_INTERVAL, (DBusTimeoutHandler)do_reading,
- transport, NULL);
- if (!_dbus_connection_add_timeout (transport->connection,
- debug_transport->read_timeout))
- {
- _dbus_timeout_unref (debug_transport->read_timeout);
- debug_transport->read_timeout = NULL;
- }
- }
-}
+ unsigned int timeout_added : 1; /**< Whether timeout has been added */
+};
-static void
-check_read_timeout (DBusTransport *transport)
+/* move messages in both directions */
+static dbus_bool_t
+move_messages (DBusTransport *transport)
{
DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport;
- dbus_bool_t need_read_timeout;
-
- if (transport->connection == NULL)
- return;
-
- _dbus_transport_ref (transport);
-
- need_read_timeout = dbus_connection_get_n_messages (transport->connection) > 0;
if (transport->disconnected)
- need_read_timeout = FALSE;
-
- if (need_read_timeout &&
- debug_transport->read_timeout == NULL)
- {
- debug_transport->read_timeout =
- _dbus_timeout_new (DEFAULT_INTERVAL, (DBusTimeoutHandler)do_reading,
- transport, NULL);
-
- if (debug_transport->read_timeout == NULL)
- goto out;
-
- if (!_dbus_connection_add_timeout (transport->connection,
- debug_transport->read_timeout))
- {
- _dbus_timeout_unref (debug_transport->read_timeout);
- debug_transport->read_timeout = NULL;
-
- goto out;
- }
- }
- else if (!need_read_timeout &&
- debug_transport->read_timeout != NULL)
- {
- _dbus_connection_remove_timeout (transport->connection,
- debug_transport->read_timeout);
- _dbus_timeout_unref (debug_transport->read_timeout);
- debug_transport->read_timeout = NULL;
- }
-
- out:
- _dbus_transport_unref (transport);
-}
-
-static void
-do_writing (DBusTransport *transport)
-{
- if (transport->disconnected)
- return;
+ return TRUE;
while (!transport->disconnected &&
_dbus_connection_have_messages_to_send (transport->connection))
DBusMessage *message, *copy;
message = _dbus_connection_get_message_to_send (transport->connection);
- _dbus_message_lock (message);
+ _dbus_assert (message != NULL);
- copy = dbus_message_new_from_message (message);
+ copy = dbus_message_copy (message);
+ if (copy == NULL)
+ return FALSE;
+
+ _dbus_message_lock (message);
_dbus_connection_message_sent (transport->connection,
message);
+
+ _dbus_verbose (" -->transporting message %s from %s %p to %s %p\n",
+ dbus_message_get_name (copy),
+ transport->is_server ? "server" : "client",
+ transport->connection,
+ debug_transport->other_end->is_server ? "server" : "client",
+ debug_transport->other_end->connection);
- _dbus_connection_queue_received_message (((DBusTransportDebug *)transport)->other_end->connection,
+ _dbus_connection_queue_received_message (debug_transport->other_end->connection,
copy);
dbus_message_unref (copy);
}
- check_read_timeout (((DBusTransportDebug *)transport)->other_end);
+ if (debug_transport->other_end &&
+ !debug_transport->other_end->disconnected &&
+ _dbus_connection_have_messages_to_send (debug_transport->other_end->connection))
+ {
+ if (!move_messages (debug_transport->other_end))
+ return FALSE;
+ }
+
+ return TRUE;
}
-static void
-check_write_timeout (DBusTransport *transport)
+static dbus_bool_t
+timeout_handler (void *data)
{
- DBusTransportDebug *debug_transport = (DBusTransportDebug *)transport;
- dbus_bool_t need_write_timeout;
+ DBusTransport *transport = data;
- if (transport->connection == NULL)
- return;
+ if (!move_messages (transport))
+ return FALSE;
- _dbus_transport_ref (transport);
+ if (!check_timeout (transport))
+ return FALSE;
- need_write_timeout = transport->messages_need_sending;
-
- if (transport->disconnected)
- need_write_timeout = FALSE;
+ return TRUE;
+}
- if (need_write_timeout &&
- debug_transport->write_timeout == NULL)
+static dbus_bool_t
+check_timeout (DBusTransport *transport)
+{
+ DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport;
+
+ if (transport->connection &&
+ transport->authenticated &&
+ (transport->messages_need_sending ||
+ (debug_transport->other_end &&
+ debug_transport->other_end->messages_need_sending)))
{
- debug_transport->write_timeout =
- _dbus_timeout_new (DEFAULT_INTERVAL, (DBusTimeoutHandler)do_writing,
- transport, NULL);
-
- if (debug_transport->write_timeout == NULL)
- goto out;
-
- if (!_dbus_connection_add_timeout (transport->connection,
- debug_transport->write_timeout))
- {
- _dbus_timeout_unref (debug_transport->write_timeout);
- debug_transport->write_timeout = NULL;
- }
+ if (!debug_transport->timeout_added)
+ {
+ /* FIXME this can be fixed now, by enabling/disabling
+ * the timeout instead of adding it here
+ */
+ if (!_dbus_connection_add_timeout (transport->connection,
+ debug_transport->timeout))
+ return FALSE;
+ debug_transport->timeout_added = TRUE;
+ }
}
- else if (!need_write_timeout &&
- debug_transport->write_timeout != NULL)
+ else
{
- _dbus_connection_remove_timeout (transport->connection,
- debug_transport->write_timeout);
- _dbus_timeout_unref (debug_transport->write_timeout);
- debug_transport->write_timeout = NULL;
+ if (debug_transport->timeout_added)
+ {
+ _dbus_connection_remove_timeout (transport->connection,
+ debug_transport->timeout);
+ debug_transport->timeout_added = FALSE;
+ }
}
- out:
- _dbus_transport_unref (transport);
+ return TRUE;
}
static void
+debug_finalize (DBusTransport *transport)
+{
+ DBusTransportDebug *debug_transport = (DBusTransportDebug*) transport;
+
+ if (debug_transport->timeout_added)
+ _dbus_connection_remove_timeout (transport->connection,
+ debug_transport->timeout);
+
+ if (debug_transport->other_end)
+ {
+ _dbus_transport_disconnect (debug_transport->other_end);
+ debug_transport->other_end = NULL;
+ }
+
+ _dbus_transport_finalize_base (transport);
+
+ _dbus_timeout_unref (debug_transport->timeout);
+
+ dbus_free (transport);
+}
+
+static dbus_bool_t
debug_handle_watch (DBusTransport *transport,
DBusWatch *watch,
unsigned int flags)
{
+ return TRUE;
}
static void
{
}
-static void
+static dbus_bool_t
debug_connection_set (DBusTransport *transport)
{
+ if (!check_timeout (transport))
+ return FALSE;
+ return TRUE;
}
static void
debug_messages_pending (DBusTransport *transport,
int messages_pending)
{
- check_write_timeout (transport);
+ while (!check_timeout (transport))
+ WAIT_FOR_MEMORY ();
}
static void
unsigned int flags,
int timeout_milliseconds)
{
+ move_messages (transport);
}
static void
debug_live_messages_changed
};
+static dbus_bool_t
+create_timeout_object (DBusTransportDebug *debug_transport)
+{
+ debug_transport->timeout = _dbus_timeout_new (DEFAULT_INTERVAL,
+ timeout_handler,
+ debug_transport, NULL);
+
+ return debug_transport->timeout != NULL;
+}
+
/**
* Creates a new debug server transport.
*
if (!_dbus_transport_init_base (&debug_transport->base,
&debug_vtable,
- TRUE))
+ TRUE, NULL))
{
dbus_free (debug_transport);
return NULL;
}
+ if (!create_timeout_object (debug_transport))
+ {
+ _dbus_transport_finalize_base (&debug_transport->base);
+ dbus_free (debug_transport);
+ return NULL;
+ }
+
debug_transport->base.authenticated = TRUE;
/* Connect the two transports */
debug_transport->other_end = client;
((DBusTransportDebug *)client)->other_end = (DBusTransport *)debug_transport;
+
+ _dbus_verbose (" new debug server transport %p created, other end %p\n",
+ debug_transport, debug_transport->other_end);
return (DBusTransport *)debug_transport;
}
*
* @param server_name name of the server transport that
* the client should try to connect to.
- * @param result address where a result code can be returned.
+ * @param error address where an error can be returned.
* @returns a new transport, or #NULL on failure.
*/
DBusTransport*
_dbus_transport_debug_client_new (const char *server_name,
- DBusResultCode *result)
+ DBusError *error)
{
DBusServer *debug_server;
DBusTransportDebug *debug_transport;
+ DBusString address;
+
+ _DBUS_ASSERT_ERROR_IS_CLEAR (error);
debug_server = _dbus_server_debug_lookup (server_name);
if (!debug_server)
{
- dbus_set_result (result, DBUS_RESULT_NO_SERVER);
+ dbus_set_error (error, DBUS_ERROR_NO_SERVER, NULL);
+ return NULL;
+ }
+
+ if (!_dbus_string_init (&address))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return NULL;
}
+ if (!_dbus_string_append (&address, "debug-pipe:name=") ||
+ !_dbus_string_append (&address, server_name))
+ {
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ _dbus_string_free (&address);
+ return NULL;
+ }
+
debug_transport = dbus_new0 (DBusTransportDebug, 1);
if (debug_transport == NULL)
{
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ _dbus_string_free (&address);
return NULL;
}
if (!_dbus_transport_init_base (&debug_transport->base,
&debug_vtable,
- FALSE))
+ FALSE, &address))
{
dbus_free (debug_transport);
- dbus_set_result (result, DBUS_RESULT_NO_MEMORY);
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ _dbus_string_free (&address);
return NULL;
}
- if (!_dbus_server_debug_accept_transport (debug_server, (DBusTransport *)debug_transport))
+ _dbus_string_free (&address);
+
+ if (!create_timeout_object (debug_transport))
{
_dbus_transport_finalize_base (&debug_transport->base);
-
- dbus_free (debug_transport);
- dbus_set_result (result, DBUS_RESULT_IO_ERROR);
+ dbus_free (debug_transport);
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+ return NULL;
+ }
+
+ if (!_dbus_server_debug_accept_transport (debug_server,
+ (DBusTransport *)debug_transport))
+ {
+ _dbus_timeout_unref (debug_transport->timeout);
+ _dbus_transport_finalize_base (&debug_transport->base);
+ dbus_free (debug_transport);
+ dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
return NULL;
-
}
/* FIXME: Prolly wrong to do this. */
debug_transport->base.authenticated = TRUE;
+
+ _dbus_verbose (" new debug client transport %p created, other end %p\n",
+ debug_transport, debug_transport->other_end);
return (DBusTransport *)debug_transport;
}