Commit 1820f3bd authored by Havoc Pennington's avatar Havoc Pennington

2003-04-24 Havoc Pennington <hp@redhat.com>

	* bus/dispatch.c: somehow missed some name_is

	* dbus/dbus-timeout.c (_dbus_timeout_set_enabled)
	(_dbus_timeout_set_interval): new

	* bus/connection.c (bus_connections_setup_connection): record time
	when each connection is first set up, and expire them after the
	auth timeout passes.
parent 0ed8f3f3
2003-04-24 Havoc Pennington <hp@redhat.com>
* bus/dispatch.c: somehow missed some name_is
* dbus/dbus-timeout.c (_dbus_timeout_set_enabled)
(_dbus_timeout_set_interval): new
* bus/connection.c (bus_connections_setup_connection): record time
when each connection is first set up, and expire them after the
auth timeout passes.
2003-04-24 Havoc Pennington <hp@redhat.com>
* dbus/dbus-message.c (dbus_message_name_is): rename
......
......@@ -27,6 +27,7 @@
#include "utils.h"
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
#include <dbus/dbus-timeout.h>
static void bus_connection_remove_transactions (DBusConnection *connection);
......@@ -39,6 +40,7 @@ struct BusConnections
int n_incomplete; /**< Length of incomplete list */
BusContext *context;
DBusHashTable *completed_by_user; /**< Number of completed connections for each UID */
DBusTimeout *expire_timeout; /**< Timeout for expiring incomplete connections. */
};
static int connection_data_slot = -1;
......@@ -55,8 +57,13 @@ typedef struct
DBusMessage *oom_message;
DBusPreallocatedSend *oom_preallocated;
BusClientPolicy *policy;
long connection_tv_sec; /**< Time when we connected (seconds component) */
long connection_tv_usec; /**< Time when we connected (microsec component) */
} BusConnectionData;
static dbus_bool_t expire_incomplete_timeout (void *data);
#define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
static dbus_bool_t
......@@ -178,10 +185,7 @@ bus_connection_disconnected (DBusConnection *connection)
* handle it other than sleeping; we can't "fail" the operation of
* disconnecting a client, and preallocating a broadcast "service is
* now gone" message for every client-service pair seems kind of
* involved. Probably we need to do that though, and also
* extend BusTransaction to be able to revert generic
* stuff, not just sending a message (so we can e.g. revert
* removal of service owners).
* involved. Probably we need to do that though.
*/
while ((service = _dbus_list_get_last (&d->services_owned)))
{
......@@ -400,34 +404,59 @@ free_connection_data (void *data)
dbus_free (d);
}
static void
call_timeout_callback (DBusTimeout *timeout,
void *data)
{
/* can return FALSE on OOM but we just let it fire again later */
dbus_timeout_handle (timeout);
}
BusConnections*
bus_connections_new (BusContext *context)
{
BusConnections *connections;
if (!connection_data_slot_ref ())
return NULL;
goto failed_0;
connections = dbus_new0 (BusConnections, 1);
if (connections == NULL)
{
connection_data_slot_unref ();
return NULL;
}
goto failed_1;
connections->completed_by_user = _dbus_hash_table_new (DBUS_HASH_ULONG,
NULL, NULL);
if (connections->completed_by_user == NULL)
{
dbus_free (connections);
connection_data_slot_unref ();
return NULL;
}
goto failed_2;
connections->expire_timeout = _dbus_timeout_new (100, /* irrelevant */
expire_incomplete_timeout,
connections, NULL);
if (connections->expire_timeout == NULL)
goto failed_3;
_dbus_timeout_set_enabled (connections->expire_timeout, FALSE);
if (!_dbus_loop_add_timeout (bus_context_get_loop (context),
connections->expire_timeout,
call_timeout_callback, NULL, NULL))
goto failed_4;
connections->refcount = 1;
connections->context = context;
return connections;
failed_4:
_dbus_timeout_unref (connections->expire_timeout);
failed_3:
_dbus_hash_table_unref (connections->completed_by_user);
failed_2:
dbus_free (connections);
failed_1:
connection_data_slot_unref ();
failed_0:
return NULL;
}
void
......@@ -474,6 +503,12 @@ bus_connections_unref (BusConnections *connections)
_dbus_assert (connections->n_completed == 0);
_dbus_loop_remove_timeout (bus_context_get_loop (connections->context),
connections->expire_timeout,
call_timeout_callback, NULL);
_dbus_timeout_unref (connections->expire_timeout);
_dbus_hash_table_unref (connections->completed_by_user);
dbus_free (connections);
......@@ -497,6 +532,9 @@ bus_connections_setup_connection (BusConnections *connections,
d->connections = connections;
d->connection = connection;
_dbus_get_current_time (&d->connection_tv_sec,
&d->connection_tv_usec);
_dbus_assert (connection_data_slot >= 0);
if (!dbus_connection_set_data (connection,
......@@ -556,7 +594,14 @@ bus_connections_setup_connection (BusConnections *connections,
dbus_connection_ref (connection);
/* Note that we might disconnect ourselves here, but it only takes
* effect on return to the main loop.
* effect on return to the main loop. We call this to free up
* expired connections if possible, and to queue the timeout for our
* own expiration.
*/
bus_connections_expire_incomplete (connections);
/* And we might also disconnect ourselves here, but again it
* only takes effect on return to main loop.
*/
if (connections->n_incomplete >
bus_context_get_max_incomplete_connections (connections->context))
......@@ -613,6 +658,85 @@ bus_connections_setup_connection (BusConnections *connections,
return retval;
}
void
bus_connections_expire_incomplete (BusConnections *connections)
{
int next_interval;
long tv_sec, tv_usec;
DBusList *link;
int auth_timeout;
if (connections->incomplete == NULL)
return;
_dbus_get_current_time (&tv_sec, &tv_usec);
auth_timeout = bus_context_get_auth_timeout (connections->context);
next_interval = -1;
link = _dbus_list_get_first_link (&connections->incomplete);
while (link != NULL)
{
DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
DBusConnection *connection;
BusConnectionData *d;
double elapsed;
connection = link->data;
d = BUS_CONNECTION_DATA (connection);
_dbus_assert (d != NULL);
elapsed = ((double) tv_sec - (double) d->connection_tv_sec) * 1000.0 +
((double) tv_usec - (double) d->connection_tv_usec) / 1000.0;
if (elapsed > (double) auth_timeout)
{
_dbus_verbose ("Timing out authentication for connection %p\n", connection);
dbus_connection_disconnect (connection);
}
else
{
/* We can end the loop, since the connections are in oldest-first order */
next_interval = auth_timeout - (int) elapsed;
_dbus_verbose ("Connection %p authentication expires in %d milliseconds\n",
connection, next_interval);
break;
}
link = next;
}
if (next_interval >= 0)
{
_dbus_timeout_set_interval (connections->expire_timeout,
next_interval);
_dbus_timeout_set_enabled (connections->expire_timeout, TRUE);
_dbus_verbose ("Enabled incomplete connections timeout with interval %d, %d incomplete connections\n",
next_interval, connections->n_incomplete);
}
else
{
_dbus_timeout_set_enabled (connections->expire_timeout, FALSE);
_dbus_verbose ("Disabled incomplete connections timeout, %d incomplete connections\n",
connections->n_incomplete);
}
}
static dbus_bool_t
expire_incomplete_timeout (void *data)
{
BusConnections *connections = data;
/* note that this may remove the timeout */
bus_connections_expire_incomplete (connections);
return TRUE;
}
dbus_bool_t
bus_connection_get_groups (DBusConnection *connection,
unsigned long **groups,
......
......@@ -32,25 +32,27 @@ typedef dbus_bool_t (* BusConnectionForeachFunction) (DBusConnection *connection
void *data);
BusConnections* bus_connections_new (BusContext *context);
void bus_connections_ref (BusConnections *connections);
void bus_connections_unref (BusConnections *connections);
dbus_bool_t bus_connections_setup_connection (BusConnections *connections,
DBusConnection *connection);
void bus_connections_foreach (BusConnections *connections,
BusConnectionForeachFunction function,
void *data);
void bus_connections_foreach_active (BusConnections *connections,
BusConnectionForeachFunction function,
void *data);
BusContext* bus_connections_get_context (BusConnections *connections);
BusContext* bus_connection_get_context (DBusConnection *connection);
BusConnections* bus_connection_get_connections (DBusConnection *connection);
BusRegistry* bus_connection_get_registry (DBusConnection *connection);
BusActivation* bus_connection_get_activation (DBusConnection *connection);
dbus_bool_t bus_connections_check_limits (BusConnections *connections,
DBusConnection *requesting_completion,
DBusError *error);
BusConnections* bus_connections_new (BusContext *context);
void bus_connections_ref (BusConnections *connections);
void bus_connections_unref (BusConnections *connections);
dbus_bool_t bus_connections_setup_connection (BusConnections *connections,
DBusConnection *connection);
void bus_connections_foreach (BusConnections *connections,
BusConnectionForeachFunction function,
void *data);
void bus_connections_foreach_active (BusConnections *connections,
BusConnectionForeachFunction function,
void *data);
BusContext* bus_connections_get_context (BusConnections *connections);
BusContext* bus_connection_get_context (DBusConnection *connection);
BusConnections* bus_connection_get_connections (DBusConnection *connection);
BusRegistry* bus_connection_get_registry (DBusConnection *connection);
BusActivation* bus_connection_get_activation (DBusConnection *connection);
dbus_bool_t bus_connections_check_limits (BusConnections *connections,
DBusConnection *requesting_completion,
DBusError *error);
void bus_connections_expire_incomplete (BusConnections *connections);
dbus_bool_t bus_connection_is_active (DBusConnection *connection);
......
......@@ -457,7 +457,7 @@ check_service_deleted_foreach (DBusConnection *connection,
connection, DBUS_MESSAGE_SERVICE_DELETED);
goto out;
}
else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED))
else if (!dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_DELETED))
{
_dbus_warn ("Received message %s on %p, expecting %s\n",
dbus_message_get_name (message),
......@@ -624,7 +624,7 @@ check_service_created_foreach (DBusConnection *connection,
connection, DBUS_MESSAGE_SERVICE_CREATED);
goto out;
}
else if (!dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
else if (!dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_CREATED))
{
_dbus_warn ("Received message %s on %p, expecting %s\n",
dbus_message_get_name (message),
......@@ -747,7 +747,7 @@ check_hello_message (BusContext *context,
_dbus_verbose ("Received %s on %p\n",
dbus_message_get_name (message), connection);
if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
_dbus_warn ("Message has wrong sender %s\n",
dbus_message_get_sender (message) ?
......@@ -757,8 +757,8 @@ check_hello_message (BusContext *context,
if (dbus_message_get_is_error (message))
{
if (dbus_message_name_is (message,
DBUS_ERROR_NO_MEMORY))
if (dbus_message_has_name (message,
DBUS_ERROR_NO_MEMORY))
{
; /* good, this is a valid response */
}
......@@ -773,8 +773,8 @@ check_hello_message (BusContext *context,
{
CheckServiceCreatedData scd;
if (dbus_message_name_is (message,
DBUS_MESSAGE_HELLO))
if (dbus_message_has_name (message,
DBUS_MESSAGE_HELLO))
{
; /* good, expected */
}
......@@ -985,7 +985,7 @@ check_nonexistent_service_activation (BusContext *context,
if (dbus_message_get_is_error (message))
{
if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
_dbus_warn ("Message has wrong sender %s\n",
dbus_message_get_sender (message) ?
......@@ -993,13 +993,13 @@ check_nonexistent_service_activation (BusContext *context,
goto out;
}
if (dbus_message_name_is (message,
DBUS_ERROR_NO_MEMORY))
if (dbus_message_has_name (message,
DBUS_ERROR_NO_MEMORY))
{
; /* good, this is a valid response */
}
else if (dbus_message_name_is (message,
DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
else if (dbus_message_has_name (message,
DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND))
{
; /* good, this is expected also */
}
......@@ -1045,7 +1045,7 @@ check_base_service_activated (BusContext *context,
message = initial_message;
dbus_message_ref (message);
if (dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
if (dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_CREATED))
{
char *service_name;
CheckServiceCreatedData scd;
......@@ -1134,7 +1134,7 @@ check_service_activated (BusContext *context,
message = initial_message;
dbus_message_ref (message);
if (dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_CREATED))
if (dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_CREATED))
{
char *service_name;
CheckServiceCreatedData scd;
......@@ -1195,7 +1195,7 @@ check_service_activated (BusContext *context,
goto out;
}
if (!dbus_message_name_is (message, DBUS_MESSAGE_ACTIVATE_SERVICE))
if (!dbus_message_has_name (message, DBUS_MESSAGE_ACTIVATE_SERVICE))
{
_dbus_warn ("Expected reply to %s, got message %s instead\n",
DBUS_MESSAGE_ACTIVATE_SERVICE,
......@@ -1380,7 +1380,7 @@ check_send_exit_to_service (BusContext *context,
dbus_message_get_name (message));
goto out;
}
else if (!dbus_message_name_is (message, DBUS_ERROR_NO_MEMORY))
else if (!dbus_message_has_name (message, DBUS_ERROR_NO_MEMORY))
{
_dbus_warn ("not expecting error %s when asking test service to exit\n",
dbus_message_get_name (message));
......@@ -1445,7 +1445,7 @@ check_got_error (BusContext *context,
error_name = first_error_name;
while (error_name != NULL)
{
if (dbus_message_name_is (message, error_name))
if (dbus_message_has_name (message, error_name))
{
error_found = TRUE;
break;
......@@ -1545,7 +1545,7 @@ check_existent_service_activation (BusContext *context,
if (dbus_message_get_is_error (message))
{
if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
_dbus_warn ("Message has wrong sender %s\n",
dbus_message_get_sender (message) ?
......@@ -1553,13 +1553,13 @@ check_existent_service_activation (BusContext *context,
goto out;
}
if (dbus_message_name_is (message,
DBUS_ERROR_NO_MEMORY))
if (dbus_message_has_name (message,
DBUS_ERROR_NO_MEMORY))
{
; /* good, this is a valid response */
}
else if (dbus_message_name_is (message,
DBUS_ERROR_SPAWN_CHILD_EXITED))
else if (dbus_message_has_name (message,
DBUS_ERROR_SPAWN_CHILD_EXITED))
{
; /* good, this is expected also */
}
......@@ -1592,7 +1592,7 @@ check_existent_service_activation (BusContext *context,
goto out;
}
got_service_deleted = dbus_message_name_is (message, DBUS_MESSAGE_SERVICE_DELETED);
got_service_deleted = dbus_message_has_name (message, DBUS_MESSAGE_SERVICE_DELETED);
got_error = dbus_message_get_is_error (message);
dbus_connection_return_message (connection, message);
......@@ -1748,7 +1748,7 @@ check_segfault_service_activation (BusContext *context,
if (dbus_message_get_is_error (message))
{
if (!dbus_message_sender_is (message, DBUS_SERVICE_DBUS))
if (!dbus_message_has_sender (message, DBUS_SERVICE_DBUS))
{
_dbus_warn ("Message has wrong sender %s\n",
dbus_message_get_sender (message) ?
......@@ -1756,12 +1756,12 @@ check_segfault_service_activation (BusContext *context,
goto out;
}
if (dbus_message_name_is (message,
if (dbus_message_has_name (message,
DBUS_ERROR_NO_MEMORY))
{
; /* good, this is a valid response */
}
else if (dbus_message_name_is (message,
else if (dbus_message_has_name (message,
DBUS_ERROR_SPAWN_CHILD_SIGNALED))
{
; /* good, this is expected also */
......
......@@ -2394,12 +2394,14 @@ dbus_connection_set_watch_functions (DBusConnection *connection,
* allocation. With Qt, QTimer::start() and QTimer::stop() can be used
* to enable and disable. The toggled function may be NULL if a main
* loop re-queries dbus_timeout_get_enabled() every time anyway.
* Whenever a timeout is toggled, its interval may change.
*
* The DBusTimeout can be queried for the timer interval using
* dbus_timeout_get_interval(). dbus_timeout_handle() should
* be called repeatedly, each time the interval elapses, starting
* after it has elapsed once. The timeout stops firing when
* it is removed with the given remove_function.
* dbus_timeout_get_interval(). dbus_timeout_handle() should be called
* repeatedly, each time the interval elapses, starting after it has
* elapsed once. The timeout stops firing when it is removed with the
* given remove_function. The timer interval may change whenever the
* timeout is added, removed, or toggled.
*
* @param connection the connection.
* @param add_function function to add a timeout.
......
......@@ -48,7 +48,7 @@ struct DBusTimeout
};
/**
* Creates a new DBusTimeout.
* Creates a new DBusTimeout, enabled by default.
* @param interval the timeout interval in milliseconds.
* @param handler function to call when the timeout occurs.
* @param data data to pass to the handler
......@@ -111,6 +111,40 @@ _dbus_timeout_unref (DBusTimeout *timeout)
}
}
/**
* Changes the timeout interval. Note that you have to disable and
* re-enable the timeout using the timeout toggle function
* (_dbus_connection_toggle_timeout() etc.) to notify the application
* of this change.
*
* @param timeout the timeout
* @param interval the new interval
*/
void
_dbus_timeout_set_interval (DBusTimeout *timeout,
int interval)
{
timeout->interval = interval;
}
/**
* Changes the timeout's enabled-ness. Note that you should use
* _dbus_connection_toggle_timeout() etc. instead, if
* the timeout is passed out to an application main loop.
* i.e. you can't use this function in the D-BUS library, it's
* only used in the message bus daemon implementation.
*
* @param timeout the timeout
* @param interval the new interval
*/
void
_dbus_timeout_set_enabled (DBusTimeout *timeout,
dbus_bool_t enabled)
{
timeout->enabled = enabled != FALSE;
}
/**
* @typedef DBusTimeoutList
*
......@@ -133,7 +167,7 @@ struct DBusTimeoutList
DBusAddTimeoutFunction add_timeout_function; /**< Callback for adding a timeout. */
DBusRemoveTimeoutFunction remove_timeout_function; /**< Callback for removing a timeout. */
DBusTimeoutToggledFunction timeout_toggled_function; /**< Callback when timeout is enabled/disabled */
DBusTimeoutToggledFunction timeout_toggled_function; /**< Callback when timeout is enabled/disabled or changes interval */
void *timeout_data; /**< Data for timeout callbacks */
DBusFreeFunction timeout_free_data_function; /**< Free function for timeout callback data */
};
......@@ -355,6 +389,11 @@ _dbus_timeout_list_toggle_timeout (DBusTimeoutList *timeout_list,
* should be called each time this interval elapses,
* starting after it elapses once.
*
* The interval may change during the life of the
* timeout; if so, the timeout will be disabled and
* re-enabled (calling the "timeout toggled function")
* to notify you of the change.
*
* @param timeout the DBusTimeout object.
* @returns the interval in milliseconds.
*/
......
......@@ -34,12 +34,16 @@ typedef struct DBusTimeoutList DBusTimeoutList;
typedef dbus_bool_t (* DBusTimeoutHandler) (void *data);
DBusTimeout* _dbus_timeout_new (int interval,
DBusTimeoutHandler handler,
void *data,
DBusFreeFunction free_data_function);
void _dbus_timeout_ref (DBusTimeout *timeout);
void _dbus_timeout_unref (DBusTimeout *timeout);
DBusTimeout* _dbus_timeout_new (int interval,
DBusTimeoutHandler handler,
void *data,
DBusFreeFunction free_data_function);
void _dbus_timeout_ref (DBusTimeout *timeout);
void _dbus_timeout_unref (DBusTimeout *timeout);
void _dbus_timeout_set_interval (DBusTimeout *timeout,
int interval);
void _dbus_timeout_set_enabled (DBusTimeout *timeout,
dbus_bool_t enabled);
DBusTimeoutList *_dbus_timeout_list_new (void);
void _dbus_timeout_list_free (DBusTimeoutList *timeout_list);
......
......@@ -77,10 +77,10 @@ filter_func (DBusMessageHandler *handler,
DBusMessage *message,
void *user_data)
{
if (dbus_message_name_is (message, "org.freedesktop.DBus.TestSuiteEcho"))
if (dbus_message_has_name (message, "org.freedesktop.DBus.TestSuiteEcho"))
return handle_echo (connection, message);
else if (dbus_message_name_is (message, "org.freedesktop.DBus.TestSuiteExit") ||
dbus_message_name_is (message, DBUS_MESSAGE_LOCAL_DISCONNECT))
else if (dbus_message_has_name (message, "org.freedesktop.DBus.TestSuiteExit") ||
dbus_message_has_name (message, DBUS_MESSAGE_LOCAL_DISCONNECT))
{
dbus_connection_disconnect (connection);
quit ();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment