1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-message-handler.c Sender/receiver of messages.
4 * Copyright (C) 2002 Red Hat Inc.
6 * Licensed under the Academic Free License version 1.2
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.
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.
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
24 #include "dbus-internals.h"
25 #include "dbus-message-handler.h"
26 #include "dbus-list.h"
27 #include "dbus-threads.h"
28 #include "dbus-connection-internal.h"
31 * @defgroup DBusMessageHandlerInternals DBusMessageHandler implementation details
32 * @ingroup DBusInternals
33 * @brief DBusMessageHandler private implementation details.
35 * The guts of DBusMessageHandler and its methods.
40 static DBusMutex *message_handler_lock = NULL;
41 DBusMutex *_dbus_message_handler_init_lock (void);
43 _dbus_message_handler_init_lock (void)
45 message_handler_lock = dbus_mutex_new ();
46 return message_handler_lock;
50 * @brief Internals of DBusMessageHandler
52 * Object that can send and receive messages.
54 struct DBusMessageHandler
56 int refcount; /**< reference count */
58 DBusHandleMessageFunction function; /**< handler function */
59 void *user_data; /**< user data for function */
60 DBusFreeFunction free_user_data; /**< free the user data */
62 DBusList *connections; /**< connections we're registered with */
66 * Add this connection to the list used by this message handler.
67 * When the message handler goes away, the connection
70 * @param handler the message handler
71 * @param connection the connection
72 * @returns #FALSE if not enough memory
75 _dbus_message_handler_add_connection (DBusMessageHandler *handler,
76 DBusConnection *connection)
80 dbus_mutex_lock (message_handler_lock);
81 /* This is a bit wasteful - we just put the connection in the list
82 * once per time it's added. :-/
84 if (!_dbus_list_prepend (&handler->connections, connection))
89 dbus_mutex_unlock (message_handler_lock);
95 * Reverses the effect of _dbus_message_handler_add_connection().
96 * @param handler the message handler
97 * @param connection the connection
100 _dbus_message_handler_remove_connection (DBusMessageHandler *handler,
101 DBusConnection *connection)
103 dbus_mutex_lock (message_handler_lock);
104 if (!_dbus_list_remove (&handler->connections, connection))
105 _dbus_warn ("Function _dbus_message_handler_remove_connection() called when the connection hadn't been added\n");
106 dbus_mutex_unlock (message_handler_lock);
111 * Handles the given message, by dispatching the handler function
112 * for this DBusMessageHandler, if any.
114 * @param handler the handler
115 * @param connection the connection that received the message
116 * @param message the message
118 * @returns what to do with the message
121 _dbus_message_handler_handle_message (DBusMessageHandler *handler,
122 DBusConnection *connection,
123 DBusMessage *message)
125 DBusHandleMessageFunction function;
128 dbus_mutex_lock (message_handler_lock);
129 function = handler->function;
130 user_data = handler->user_data;
131 dbus_mutex_unlock (message_handler_lock);
133 /* This function doesn't ref handler/connection/message
134 * since that's done in dbus_connection_dispatch_message().
136 if (function != NULL)
137 return (* function) (handler, connection, message, user_data);
139 return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
145 * @defgroup DBusMessageHandler DBusMessageHandler
147 * @brief Message processor
149 * A DBusMessageHandler is an object that can send and receive
150 * messages. Typically the handler is registered with one or
151 * more DBusConnection objects and processes some types of
152 * messages received from the connection.
158 * @typedef DBusMessageHandler
160 * Opaque data type representing a message handler.
164 * Creates a new message handler. The handler function
165 * may be #NULL for a no-op handler or a handler to
166 * be assigned a function later.
168 * @param function function to call to handle a message
169 * @param user_data data to pass to the function
170 * @param free_user_data function to call to free the user data
171 * @returns a new DBusMessageHandler or #NULL if no memory.
174 dbus_message_handler_new (DBusHandleMessageFunction function,
176 DBusFreeFunction free_user_data)
178 DBusMessageHandler *handler;
180 handler = dbus_new (DBusMessageHandler, 1);
185 handler->refcount = 1;
186 handler->function = function;
187 handler->user_data = user_data;
188 handler->free_user_data = free_user_data;
189 handler->connections = NULL;
195 * Increments the reference count on a message handler.
197 * @param handler the handler
200 dbus_message_handler_ref (DBusMessageHandler *handler)
202 dbus_mutex_lock (message_handler_lock);
203 _dbus_assert (handler != NULL);
205 handler->refcount += 1;
206 dbus_mutex_unlock (message_handler_lock);
210 * Decrements the reference count on a message handler,
211 * freeing the handler if the count reaches 0.
213 * @param handler the handler
216 dbus_message_handler_unref (DBusMessageHandler *handler)
220 dbus_mutex_lock (message_handler_lock);
222 _dbus_assert (handler != NULL);
223 _dbus_assert (handler->refcount > 0);
225 handler->refcount -= 1;
226 refcount = handler->refcount;
228 dbus_mutex_unlock (message_handler_lock);
234 if (handler->free_user_data)
235 (* handler->free_user_data) (handler->user_data);
237 link = _dbus_list_get_first_link (&handler->connections);
240 DBusConnection *connection = link->data;
242 _dbus_connection_handler_destroyed_locked (connection, handler);
244 link = _dbus_list_get_next_link (&handler->connections, link);
247 _dbus_list_clear (&handler->connections);
254 * Gets the user data for the handler (the same user data
255 * passed to the handler function.)
257 * @param handler the handler
258 * @returns the user data
261 dbus_message_handler_get_data (DBusMessageHandler *handler)
264 dbus_mutex_lock (message_handler_lock);
265 user_data = handler->user_data;
266 dbus_mutex_unlock (message_handler_lock);
271 * Sets the user data for the handler (the same user data
272 * to be passed to the handler function). Frees any previously-existing
273 * user data with the previous free_user_data function.
275 * @param handler the handler
276 * @param user_data the user data
277 * @param free_user_data free function for the data
280 dbus_message_handler_set_data (DBusMessageHandler *handler,
282 DBusFreeFunction free_user_data)
284 DBusFreeFunction old_free_func;
287 dbus_mutex_lock (message_handler_lock);
288 old_free_func = handler->free_user_data;
289 old_user_data = handler->user_data;
291 handler->user_data = user_data;
292 handler->free_user_data = free_user_data;
293 dbus_mutex_unlock (message_handler_lock);
296 (* old_free_func) (old_user_data);
301 * Sets the handler function. Call dbus_message_handler_set_data()
302 * to set the user data for the function.
304 * @param handler the handler
305 * @param function the function
308 dbus_message_handler_set_function (DBusMessageHandler *handler,
309 DBusHandleMessageFunction function)
311 dbus_mutex_lock (message_handler_lock);
312 handler->function = function;
313 dbus_mutex_unlock (message_handler_lock);