Commit 1dd3f178 authored by Havoc Pennington's avatar Havoc Pennington

2003-08-30 Havoc Pennington <hp@pobox.com>

	* dbus/dbus-connection.c: purge DBusMessageHandler

	* dbus/dbus-message-handler.c: remove DBusMessageHandler, just
	use callbacks everywhere
parent 5fd1e389
2003-08-30 Havoc Pennington <hp@pobox.com>
* dbus/dbus-connection.c: purge DBusMessageHandler
* dbus/dbus-message-handler.c: remove DBusMessageHandler, just
use callbacks everywhere
2003-08-30 Havoc Pennington <hp@pobox.com>
* test/data/valid-config-files/system.d/test.conf: change to
......
......@@ -32,8 +32,6 @@
#include <dbus/dbus-internals.h>
#include <string.h>
static dbus_int32_t message_handler_slot = -1;
typedef struct
{
BusContext *context;
......@@ -316,61 +314,21 @@ bus_dispatch (DBusConnection *connection,
}
static DBusHandlerResult
bus_dispatch_message_handler (DBusMessageHandler *handler,
DBusConnection *connection,
DBusMessage *message,
void *user_data)
bus_dispatch_message_filter (DBusConnection *connection,
DBusMessage *message,
void *user_data)
{
return bus_dispatch (connection, message);
}
static void
free_message_handler (void *data)
{
DBusMessageHandler *handler = data;
_dbus_assert (message_handler_slot >= 0);
dbus_message_handler_unref (handler);
dbus_connection_free_data_slot (&message_handler_slot);
}
dbus_bool_t
bus_dispatch_add_connection (DBusConnection *connection)
{
DBusMessageHandler *handler;
if (!dbus_connection_allocate_data_slot (&message_handler_slot))
{
if (!dbus_connection_add_filter (connection,
bus_dispatch_message_filter,
NULL, NULL))
return FALSE;
handler = dbus_message_handler_new (bus_dispatch_message_handler, NULL, NULL);
if (handler == NULL)
{
dbus_connection_free_data_slot (&message_handler_slot);
return FALSE;
}
if (!dbus_connection_add_filter (connection, handler))
{
dbus_message_handler_unref (handler);
dbus_connection_free_data_slot (&message_handler_slot);
return FALSE;
}
_dbus_assert (message_handler_slot >= 0);
if (!dbus_connection_set_data (connection,
message_handler_slot,
handler,
free_message_handler))
{
dbus_message_handler_unref (handler);
dbus_connection_free_data_slot (&message_handler_slot);
return FALSE;
}
return TRUE;
}
......@@ -380,9 +338,9 @@ bus_dispatch_remove_connection (DBusConnection *connection)
/* Here we tell the bus driver that we want to get off. */
bus_driver_remove_connection (connection);
dbus_connection_set_data (connection,
message_handler_slot,
NULL, NULL);
dbus_connection_remove_filter (connection,
bus_dispatch_message_filter,
NULL);
}
#ifdef DBUS_BUILD_TESTS
......
......@@ -102,10 +102,9 @@ remove_client_timeout (DBusTimeout *timeout,
}
static DBusHandlerResult
client_disconnect_handler (DBusMessageHandler *handler,
DBusConnection *connection,
DBusMessage *message,
void *user_data)
client_disconnect_filter (DBusConnection *connection,
DBusMessage *message,
void *user_data)
{
if (!dbus_message_is_signal (message,
DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
......@@ -128,35 +127,15 @@ client_disconnect_handler (DBusMessageHandler *handler,
return DBUS_HANDLER_RESULT_HANDLED;
}
static dbus_int32_t handler_slot = -1;
static void
free_handler (void *data)
{
DBusMessageHandler *handler = data;
dbus_message_handler_unref (handler);
dbus_connection_free_data_slot (&handler_slot);
}
dbus_bool_t
bus_setup_debug_client (DBusConnection *connection)
{
DBusMessageHandler *disconnect_handler;
dbus_bool_t retval;
disconnect_handler = dbus_message_handler_new (client_disconnect_handler,
NULL, NULL);
if (disconnect_handler == NULL)
return FALSE;
dbus_bool_t retval;
if (!dbus_connection_add_filter (connection,
disconnect_handler))
{
dbus_message_handler_unref (disconnect_handler);
return FALSE;
}
client_disconnect_filter,
NULL, NULL))
return FALSE;
retval = FALSE;
......@@ -184,25 +163,15 @@ bus_setup_debug_client (DBusConnection *connection)
if (!_dbus_list_append (&clients, connection))
goto out;
if (!dbus_connection_allocate_data_slot (&handler_slot))
goto out;
/* Set up handler to be destroyed */
if (!dbus_connection_set_data (connection, handler_slot,
disconnect_handler,
free_handler))
{
dbus_connection_free_data_slot (&handler_slot);
goto out;
}
retval = TRUE;
out:
if (!retval)
{
dbus_message_handler_unref (disconnect_handler); /* unregisters it */
dbus_connection_remove_filter (connection,
client_disconnect_filter,
NULL);
dbus_connection_set_watch_functions (connection,
NULL, NULL, NULL, NULL, NULL);
......
......@@ -16,7 +16,6 @@ dbusinclude_HEADERS= \
dbus-macros.h \
dbus-memory.h \
dbus-message.h \
dbus-message-handler.h \
dbus-pending-call.h \
dbus-protocol.h \
dbus-server.h \
......@@ -41,7 +40,6 @@ DBUS_LIB_SOURCES= \
dbus-keyring.c \
dbus-keyring.h \
dbus-message.c \
dbus-message-handler.c \
dbus-message-internal.h \
dbus-object-tree.c \
dbus-object-tree.h \
......
......@@ -77,15 +77,6 @@ void _dbus_connection_do_iteration (DBusConnection
unsigned int flags,
int timeout_milliseconds);
void _dbus_connection_notify_disconnected (DBusConnection *connection);
void _dbus_connection_handler_destroyed_locked (DBusConnection *connection,
DBusMessageHandler *handler);
dbus_bool_t _dbus_message_handler_add_connection (DBusMessageHandler *handler,
DBusConnection *connection);
void _dbus_message_handler_remove_connection (DBusMessageHandler *handler,
DBusConnection *connection);
DBusHandlerResult _dbus_message_handler_handle_message (DBusMessageHandler *handler,
DBusConnection *connection,
DBusMessage *message);
DBusPendingCall* _dbus_pending_call_new (DBusConnection *connection,
int timeout_milliseconds,
......
......@@ -31,7 +31,6 @@
#include "dbus-list.h"
#include "dbus-hash.h"
#include "dbus-message-internal.h"
#include "dbus-message-handler.h"
#include "dbus-threads.h"
#include "dbus-protocol.h"
#include "dbus-dataslot.h"
......@@ -125,6 +124,16 @@
* @{
*/
typedef struct DBusMessageFilter DBusMessageFilter;
struct DBusMessageFilter
{
DBusAtomic refcount;
DBusHandleMessageFunction function;
void *user_data;
DBusFreeFunction free_user_data_function;
};
static dbus_bool_t _dbus_modify_sigpipe = TRUE;
/**
......@@ -189,6 +198,26 @@ static void _dbus_connection_update_dispatch_status_and_unlock (DB
DBusDispatchStatus new_status);
static void _dbus_connection_last_unref (DBusConnection *connection);
static void
_dbus_message_filter_ref (DBusMessageFilter *filter)
{
_dbus_assert (filter->refcount.value > 0);
_dbus_atomic_inc (&filter->refcount);
}
static void
_dbus_message_filter_unref (DBusMessageFilter *filter)
{
_dbus_assert (filter->refcount.value > 0);
if (_dbus_atomic_dec (&filter->refcount) == 1)
{
if (filter->free_user_data_function)
(* filter->free_user_data_function) (filter->user_data);
dbus_free (filter);
}
}
/**
* Acquires the connection lock.
......@@ -977,40 +1006,6 @@ _dbus_connection_get_next_client_serial (DBusConnection *connection)
return serial;
}
/**
* Used to notify a connection when a DBusMessageHandler is
* destroyed, so the connection can drop any reference
* to the handler. This is a private function, but still
* takes the connection lock. Don't call it with the lock held.
*
* @todo needs to check in pending_replies too.
*
* @param connection the connection
* @param handler the handler
*/
void
_dbus_connection_handler_destroyed_locked (DBusConnection *connection,
DBusMessageHandler *handler)
{
DBusList *link;
CONNECTION_LOCK (connection);
link = _dbus_list_get_first_link (&connection->filter_list);
while (link != NULL)
{
DBusMessageHandler *h = link->data;
DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
if (h == handler)
_dbus_list_remove_link (&connection->filter_list,
link);
link = next;
}
CONNECTION_UNLOCK (connection);
}
/**
* A callback for use with dbus_watch_new() to create a DBusWatch.
*
......@@ -1173,18 +1168,22 @@ _dbus_connection_last_unref (DBusConnection *connection)
connection->timeouts = NULL;
_dbus_data_slot_list_free (&connection->slot_list);
/* ---- Done with stuff that invokes application callbacks */
link = _dbus_list_get_first_link (&connection->filter_list);
while (link != NULL)
{
DBusMessageHandler *h = link->data;
DBusMessageFilter *filter = link->data;
DBusList *next = _dbus_list_get_next_link (&connection->filter_list, link);
_dbus_message_handler_remove_connection (h, connection);
filter->function = NULL;
_dbus_message_filter_unref (filter); /* calls app callback */
link->data = NULL;
link = next;
}
_dbus_list_clear (&connection->filter_list);
/* ---- Done with stuff that invokes application callbacks */
_dbus_object_tree_unref (connection->objects);
......@@ -2456,7 +2455,7 @@ dbus_connection_dispatch (DBusConnection *connection)
}
_dbus_list_foreach (&filter_list_copy,
(DBusForeachFunction)dbus_message_handler_ref,
(DBusForeachFunction)_dbus_message_filter_ref,
NULL);
/* We're still protected from dispatch() reentrancy here
......@@ -2467,12 +2466,11 @@ dbus_connection_dispatch (DBusConnection *connection)
link = _dbus_list_get_first_link (&filter_list_copy);
while (link != NULL)
{
DBusMessageHandler *handler = link->data;
DBusMessageFilter *filter = link->data;
DBusList *next = _dbus_list_get_next_link (&filter_list_copy, link);
_dbus_verbose (" running filter on message %p\n", message);
result = _dbus_message_handler_handle_message (handler, connection,
message);
result = (* filter->function) (connection, message, filter->user_data);
if (result != DBUS_HANDLER_RESULT_NOT_YET_HANDLED)
break;
......@@ -2481,7 +2479,7 @@ dbus_connection_dispatch (DBusConnection *connection)
}
_dbus_list_foreach (&filter_list_copy,
(DBusForeachFunction)dbus_message_handler_unref,
(DBusForeachFunction)_dbus_message_filter_unref,
NULL);
_dbus_list_clear (&filter_list_copy);
......@@ -2928,83 +2926,126 @@ dbus_connection_set_unix_user_function (DBusConnection *connection,
}
/**
* Adds a message filter. Filters are handlers that are run on
* all incoming messages, prior to the objects
* registered with dbus_connection_register_object().
* Filters are run in the order that they were added.
* The same handler can be added as a filter more than once, in
* which case it will be run more than once.
* Filters added during a filter callback won't be run on the
* message being processed.
*
* The connection does NOT add a reference to the message handler;
* instead, if the message handler is finalized, the connection simply
* forgets about it. Thus the caller of this function must keep a
* reference to the message handler.
* Adds a message filter. Filters are handlers that are run on all
* incoming messages, prior to the objects registered with
* dbus_connection_register_object_path(). Filters are run in the
* order that they were added. The same handler can be added as a
* filter more than once, in which case it will be run more than once.
* Filters added during a filter callback won't be run on the message
* being processed.
*
* @todo we don't run filters on messages while blocking without
* entering the main loop, since filters are run as part of
* dbus_connection_dispatch().
*
* @param connection the connection
* @param handler the handler
* @param function function to handle messages
* @param user_data user data to pass to the function
* @param free_data_function function to use for freeing user data
* @returns #TRUE on success, #FALSE if not enough memory.
*/
dbus_bool_t
dbus_connection_add_filter (DBusConnection *connection,
DBusMessageHandler *handler)
dbus_connection_add_filter (DBusConnection *connection,
DBusHandleMessageFunction function,
void *user_data,
DBusFreeFunction free_data_function)
{
DBusMessageFilter *filter;
_dbus_return_val_if_fail (connection != NULL, FALSE);
_dbus_return_val_if_fail (handler != NULL, FALSE);
_dbus_return_val_if_fail (function != NULL, FALSE);
filter = dbus_new0 (DBusMessageFilter, 1);
if (filter == NULL)
return FALSE;
filter->refcount.value = 1;
CONNECTION_LOCK (connection);
if (!_dbus_message_handler_add_connection (handler, connection))
{
CONNECTION_UNLOCK (connection);
return FALSE;
}
if (!_dbus_list_append (&connection->filter_list,
handler))
filter))
{
_dbus_message_handler_remove_connection (handler, connection);
_dbus_message_filter_unref (filter);
CONNECTION_UNLOCK (connection);
return FALSE;
}
/* Fill in filter after all memory allocated,
* so we don't run the free_user_data_function
* if the add_filter() fails
*/
filter->function = function;
filter->user_data = user_data;
filter->free_user_data_function = free_data_function;
CONNECTION_UNLOCK (connection);
return TRUE;
}
/**
* Removes a previously-added message filter. It is a programming
* error to call this function for a handler that has not
* been added as a filter. If the given handler was added
* more than once, only one instance of it will be removed
* (the most recently-added instance).
* error to call this function for a handler that has not been added
* as a filter. If the given handler was added more than once, only
* one instance of it will be removed (the most recently-added
* instance).
*
* @param connection the connection
* @param handler the handler to remove
*
*/
void
dbus_connection_remove_filter (DBusConnection *connection,
DBusMessageHandler *handler)
dbus_connection_remove_filter (DBusConnection *connection,
DBusHandleMessageFunction function,
void *user_data)
{
DBusList *link;
DBusMessageFilter *filter;
_dbus_return_if_fail (connection != NULL);
_dbus_return_if_fail (handler != NULL);
_dbus_return_if_fail (function != NULL);
CONNECTION_LOCK (connection);
if (!_dbus_list_remove_last (&connection->filter_list, handler))
filter = NULL;
link = _dbus_list_get_last_link (&connection->filter_list);
while (link != NULL)
{
_dbus_warn ("Tried to remove a DBusConnection filter that had not been added\n");
CONNECTION_UNLOCK (connection);
return;
filter = link->data;
if (filter->function == function &&
filter->user_data == user_data)
{
_dbus_list_remove_link (&connection->filter_list, link);
filter->function = NULL;
break;
}
link = _dbus_list_get_prev_link (&connection->filter_list, link);
}
CONNECTION_UNLOCK (connection);
_dbus_message_handler_remove_connection (handler, connection);
#ifndef DBUS_DISABLE_CHECKS
if (filter == NULL)
{
_dbus_warn ("Attempt to remove filter function %p user data %p, but no such filter has been added\n",
function, user_data);
return;
}
#endif
/* Call application code */
if (filter->free_user_data_function)
(* filter->free_user_data_function) (filter->user_data);
CONNECTION_UNLOCK (connection);
filter->free_user_data_function = NULL;
filter->user_data = NULL;
_dbus_message_filter_unref (filter);
}
/**
......
......@@ -35,7 +35,6 @@ DBUS_BEGIN_DECLS;
typedef struct DBusWatch DBusWatch;
typedef struct DBusTimeout DBusTimeout;
typedef struct DBusMessageHandler DBusMessageHandler;
typedef struct DBusPreallocatedSend DBusPreallocatedSend;
typedef struct DBusPendingCall DBusPendingCall;
typedef struct DBusConnection DBusConnection;
......@@ -89,6 +88,11 @@ typedef dbus_bool_t (* DBusAllowUnixUserFunction) (DBusConnection *connection,
typedef void (* DBusPendingCallNotifyFunction) (DBusPendingCall *pending,
void *user_data);
typedef DBusHandlerResult (* DBusHandleMessageFunction) (DBusConnection *connection,
DBusMessage *message,
void *user_data);
DBusConnection* dbus_connection_open (const char *address,
DBusError *error);
void dbus_connection_ref (DBusConnection *connection);
......@@ -162,11 +166,16 @@ void dbus_timeout_set_data (DBusTimeout *timeout,
dbus_bool_t dbus_timeout_handle (DBusTimeout *timeout);
dbus_bool_t dbus_timeout_get_enabled (DBusTimeout *timeout);
/* Handlers */
dbus_bool_t dbus_connection_add_filter (DBusConnection *connection,
DBusMessageHandler *handler);
void dbus_connection_remove_filter (DBusConnection *connection,
DBusMessageHandler *handler);
/* Filters */
dbus_bool_t dbus_connection_add_filter (DBusConnection *connection,
DBusHandleMessageFunction function,
void *user_data,
DBusFreeFunction free_data_function);
void dbus_connection_remove_filter (DBusConnection *connection,
DBusHandleMessageFunction function,
void *user_data);
/* Other */
dbus_bool_t dbus_connection_allocate_data_slot (dbus_int32_t *slot_p);
......
......@@ -233,11 +233,10 @@ _DBUS_DECLARE_GLOBAL_LOCK (connection_slots);
_DBUS_DECLARE_GLOBAL_LOCK (server_slots);
_DBUS_DECLARE_GLOBAL_LOCK (message_slots);
_DBUS_DECLARE_GLOBAL_LOCK (atomic);
_DBUS_DECLARE_GLOBAL_LOCK (message_handler);
_DBUS_DECLARE_GLOBAL_LOCK (bus);
_DBUS_DECLARE_GLOBAL_LOCK (shutdown_funcs);
_DBUS_DECLARE_GLOBAL_LOCK (system_users);
#define _DBUS_N_GLOBAL_LOCKS (9)
#define _DBUS_N_GLOBAL_LOCKS (8)
dbus_bool_t _dbus_threads_init_debug (void);
......
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-message-handler.c Sender/receiver of messages.
*
* Copyright (C) 2002, 2003 Red Hat Inc.
*
* Licensed under the Academic Free License version 1.2
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "dbus-internals.h"
#include "dbus-message-handler.h"
#include "dbus-list.h"
#include "dbus-threads.h"
#include "dbus-test.h"
#include "dbus-connection-internal.h"
/**
* @defgroup DBusMessageHandlerInternals DBusMessageHandler implementation details
* @ingroup DBusInternals
* @brief DBusMessageHandler private implementation details.
*
* The guts of DBusMessageHandler and its methods.
*
* @{
*/
_DBUS_DEFINE_GLOBAL_LOCK (message_handler);
/**
* @brief Internals of DBusMessageHandler