2003-01-08 Havoc Pennington <hp@pobox.com>
[platform/upstream/dbus.git] / dbus / dbus-message-handler.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* dbus-message-handler.c Sender/receiver of messages.
3  *
4  * Copyright (C) 2002  Red Hat Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
7  * 
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.
12  *
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.
17  * 
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
21  *
22  */
23
24 #include "dbus-internals.h"
25 #include "dbus-message-handler.h"
26 #include "dbus-list.h"
27 #include "dbus-connection-internal.h"
28
29 /**
30  * @defgroup DBusMessageHandlerInternals DBusMessageHandler implementation details
31  * @ingroup DBusInternals
32  * @brief DBusMessageHandler private implementation details.
33  *
34  * The guts of DBusMessageHandler and its methods.
35  *
36  * @{
37  */
38
39
40 /**
41  * @brief Internals of DBusMessageHandler
42  * 
43  * Object that can send and receive messages.
44  */
45 struct DBusMessageHandler
46 {
47   int refcount;                                   /**< reference count */
48
49   DBusHandleMessageFunction function;             /**< handler function */
50   void                     *user_data;            /**< user data for function */
51   DBusFreeFunction          free_user_data;       /**< free the user data */
52
53   DBusList *connections;                          /**< connections we're registered with */
54 };
55
56 /**
57  * Add this connection to the list used by this message handler.
58  * When the message handler goes away, the connection
59  * will be notified.
60  *
61  * @param handler the message handler
62  * @param connection the connection
63  * @returns #FALSE if not enough memory
64  */
65 dbus_bool_t
66 _dbus_message_handler_add_connection (DBusMessageHandler *handler,
67                                       DBusConnection     *connection)
68 {
69   /* This is a bit wasteful - we just put the connection in the list
70    * once per time it's added. :-/
71    */
72   if (!_dbus_list_prepend (&handler->connections, connection))
73     return FALSE;
74
75   return TRUE;
76 }
77
78 /**
79  * Reverses the effect of _dbus_message_handler_add_connection().
80  * @param handler the message handler
81  * @param connection the connection
82  */
83 void
84 _dbus_message_handler_remove_connection (DBusMessageHandler *handler,
85                                          DBusConnection     *connection)
86 {
87   if (!_dbus_list_remove (&handler->connections, connection))
88     _dbus_warn ("Function _dbus_message_handler_remove_connection() called when the connection hadn't been added\n");
89 }
90
91
92 /**
93  * Handles the given message, by dispatching the handler function
94  * for this DBusMessageHandler, if any.
95  * 
96  * @param handler the handler
97  * @param connection the connection that received the message
98  * @param message the message
99  *
100  * @returns what to do with the message
101  */
102 DBusHandlerResult
103 _dbus_message_handler_handle_message (DBusMessageHandler        *handler,
104                                       DBusConnection            *connection,
105                                       DBusMessage               *message)
106 {
107   /* This function doesn't ref handler/connection/message
108    * since that's done in dbus_connection_dispatch_message().
109    */
110   if (handler->function != NULL)
111     return (* handler->function) (handler, connection, message, handler->user_data);
112   else
113     return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
114 }
115
116 /** @} */
117
118 /**
119  * @defgroup DBusMessageHandler DBusMessageHandler
120  * @ingroup  DBus
121  * @brief Message processor  
122  *
123  * A DBusMessageHandler is an object that can send and receive
124  * messages. Typically the handler is registered with one or
125  * more DBusConnection objects and processes some types of
126  * messages received from the connection.
127  *
128  * @{
129  */
130
131 /**
132  * @typedef DBusMessageHandler
133  *
134  * Opaque data type representing a message handler.
135  */
136
137 /**
138  * Creates a new message handler. The handler function
139  * may be #NULL for a no-op handler or a handler to
140  * be assigned a function later.
141  *
142  * @param function function to call to handle a message
143  * @param user_data data to pass to the function
144  * @param free_user_data function to call to free the user data
145  * @returns a new DBusMessageHandler or #NULL if no memory.
146  */
147 DBusMessageHandler*
148 dbus_message_handler_new (DBusHandleMessageFunction function,
149                           void                     *user_data,
150                           DBusFreeFunction          free_user_data)
151 {
152   DBusMessageHandler *handler;
153
154   handler = dbus_new (DBusMessageHandler, 1);
155
156   if (handler == NULL)
157     return NULL;
158   
159   handler->refcount = 1;
160   handler->function = function;
161   handler->user_data = user_data;
162   handler->free_user_data = free_user_data;
163   handler->connections = NULL;
164
165   return handler;
166 }
167
168 /**
169  * Increments the reference count on a message handler.
170  *
171  * @param handler the handler
172  */
173 void
174 dbus_message_handler_ref (DBusMessageHandler *handler)
175 {
176   _dbus_assert (handler != NULL);
177   
178   handler->refcount += 1;
179 }
180
181 /**
182  * Decrements the reference count on a message handler,
183  * freeing the handler if the count reaches 0.
184  *
185  * @param handler the handler
186  */
187 void
188 dbus_message_handler_unref (DBusMessageHandler *handler)
189 {
190   _dbus_assert (handler != NULL);
191   _dbus_assert (handler->refcount > 0);
192
193   handler->refcount -= 1;
194   if (handler->refcount == 0)
195     {
196       DBusList *link;
197       
198       if (handler->free_user_data)
199         (* handler->free_user_data) (handler->user_data);
200        
201       link = _dbus_list_get_first_link (&handler->connections);
202        while (link != NULL)
203          {
204            DBusConnection *connection = link->data;
205
206            _dbus_connection_handler_destroyed (connection, handler);
207            
208            link = _dbus_list_get_next_link (&handler->connections, link);
209          }
210
211        _dbus_list_clear (&handler->connections);
212
213        dbus_free (handler);
214     }
215 }
216
217 /**
218  * Gets the user data for the handler (the same user data
219  * passed to the handler function.)
220  *
221  * @param handler the handler
222  * @returns the user data
223  */
224 void*
225 dbus_message_handler_get_data (DBusMessageHandler *handler)
226 {
227   return handler->user_data;
228 }
229
230 /**
231  * Sets the user data for the handler (the same user data
232  * to be passed to the handler function). Frees any previously-existing
233  * user data with the previous free_user_data function.
234  *
235  * @param handler the handler
236  * @param user_data the user data
237  * @param free_user_data free function for the data
238  */
239 void
240 dbus_message_handler_set_data (DBusMessageHandler *handler,
241                                void               *user_data,
242                                DBusFreeFunction    free_user_data)
243 {
244   if (handler->free_user_data)
245     (* handler->free_user_data) (handler->user_data);
246
247   handler->user_data = user_data;
248   handler->free_user_data = free_user_data;
249 }
250
251 /**
252  * Sets the handler function. Call dbus_message_handler_set_data()
253  * to set the user data for the function.
254  *
255  * @param handler the handler
256  * @param function the function
257  */
258 void
259 dbus_message_handler_set_function (DBusMessageHandler        *handler,
260                                    DBusHandleMessageFunction  function)
261 {
262   handler->function = function;
263 }
264
265 /** @} */