summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-message-handler.c
blob: 5f12d2387afd4d22be4347ccc047cd5276c8399a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
/* -*- mode: C; c-file-style: "gnu" -*- */
/* dbus-message-handler.c Sender/receiver of messages.
 *
 * Copyright (C) 2002  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-connection-internal.h"

/**
 * @defgroup DBusMessageHandlerInternals DBusMessageHandler implementation details
 * @ingroup DBusInternals
 * @brief DBusMessageHandler private implementation details.
 *
 * The guts of DBusMessageHandler and its methods.
 *
 * @{
 */


/**
 * @brief Internals of DBusMessageHandler
 * 
 * Object that can send and receive messages.
 */
struct DBusMessageHandler
{
  int refcount;                                   /**< reference count */

  DBusHandleMessageFunction function;             /**< handler function */
  void                     *user_data;            /**< user data for function */
  DBusFreeFunction          free_user_data;       /**< free the user data */

  DBusList *connections;                          /**< connections we're registered with */
};

/**
 * Add this connection to the list used by this message handler.
 * When the message handler goes away, the connection
 * will be notified.
 *
 * @param handler the message handler
 * @param connection the connection
 * @returns #FALSE if not enough memory
 */
dbus_bool_t
_dbus_message_handler_add_connection (DBusMessageHandler *handler,
                                      DBusConnection     *connection)
{
  /* This is a bit wasteful - we just put the connection in the list
   * once per time it's added. :-/
   */
  if (!_dbus_list_prepend (&handler->connections, connection))
    return FALSE;

  return TRUE;
}

/**
 * Reverses the effect of _dbus_message_handler_add_connection().
 * @param handler the message handler
 * @param connection the connection
 */
void
_dbus_message_handler_remove_connection (DBusMessageHandler *handler,
                                         DBusConnection     *connection)
{
  if (!_dbus_list_remove (&handler->connections, connection))
    _dbus_warn ("Function _dbus_message_handler_remove_connection() called when the connection hadn't been added\n");
}


/**
 * Handles the given message, by dispatching the handler function
 * for this DBusMessageHandler, if any.
 * 
 * @param handler the handler
 * @param connection the connection that received the message
 * @param message the message
 *
 * @returns what to do with the message
 */
DBusHandlerResult
_dbus_message_handler_handle_message (DBusMessageHandler        *handler,
                                      DBusConnection            *connection,
                                      DBusMessage               *message)
{
  /* This function doesn't ref handler/connection/message
   * since that's done in dbus_connection_dispatch_message().
   */
  if (handler->function != NULL)
    return (* handler->function) (handler, connection, message, handler->user_data);
  else
    return DBUS_HANDLER_RESULT_ALLOW_MORE_HANDLERS;
}

/** @} */

/**
 * @defgroup DBusMessageHandler DBusMessageHandler
 * @ingroup  DBus
 * @brief Message processor  
 *
 * A DBusMessageHandler is an object that can send and receive
 * messages. Typically the handler is registered with one or
 * more DBusConnection objects and processes some types of
 * messages received from the connection.
 *
 * @{
 */

/**
 * @typedef DBusMessageHandler
 *
 * Opaque data type representing a message handler.
 */

/**
 * Creates a new message handler. The handler function
 * may be #NULL for a no-op handler or a handler to
 * be assigned a function later.
 *
 * @param function function to call to handle a message
 * @param user_data data to pass to the function
 * @param free_user_data function to call to free the user data
 * @returns a new DBusMessageHandler or #NULL if no memory.
 */
DBusMessageHandler*
dbus_message_handler_new (DBusHandleMessageFunction function,
                          void                     *user_data,
                          DBusFreeFunction          free_user_data)
{
  DBusMessageHandler *handler;

  handler = dbus_new (DBusMessageHandler, 1);

  if (handler == NULL)
    return NULL;
  
  handler->refcount = 1;
  handler->function = function;
  handler->user_data = user_data;
  handler->free_user_data = free_user_data;
  handler->connections = NULL;

  return handler;
}

/**
 * Increments the reference count on a message handler.
 *
 * @param handler the handler
 */
void
dbus_message_handler_ref (DBusMessageHandler *handler)
{
  _dbus_assert (handler != NULL);
  
  handler->refcount += 1;
}

/**
 * Decrements the reference count on a message handler,
 * freeing the handler if the count reaches 0.
 *
 * @param handler the handler
 */
void
dbus_message_handler_unref (DBusMessageHandler *handler)
{
  _dbus_assert (handler != NULL);
  _dbus_assert (handler->refcount > 0);

  handler->refcount -= 1;
  if (handler->refcount == 0)
    {
      DBusList *link;
      
      if (handler->free_user_data)
        (* handler->free_user_data) (handler->user_data);
       
      link = _dbus_list_get_first_link (&handler->connections);
       while (link != NULL)
         {
           DBusConnection *connection = link->data;

           _dbus_connection_handler_destroyed (connection, handler);
           
           link = _dbus_list_get_next_link (&handler->connections, link);
         }

       _dbus_list_clear (&handler->connections);

       dbus_free (handler);
    }
}

/**
 * Gets the user data for the handler (the same user data
 * passed to the handler function.)
 *
 * @param handler the handler
 * @returns the user data
 */
void*
dbus_message_handler_get_data (DBusMessageHandler *handler)
{
  return handler->user_data;
}

/**
 * Sets the user data for the handler (the same user data
 * to be passed to the handler function). Frees any previously-existing
 * user data with the previous free_user_data function.
 *
 * @param handler the handler
 * @param user_data the user data
 * @param free_user_data free function for the data
 */
void
dbus_message_handler_set_data (DBusMessageHandler *handler,
                               void               *user_data,
                               DBusFreeFunction    free_user_data)
{
  if (handler->free_user_data)
    (* handler->free_user_data) (handler->user_data);

  handler->user_data = user_data;
  handler->free_user_data = free_user_data;
}

/**
 * Sets the handler function. Call dbus_message_handler_set_data()
 * to set the user data for the function.
 *
 * @param handler the handler
 * @param function the function
 */
void
dbus_message_handler_set_function (DBusMessageHandler        *handler,
                                   DBusHandleMessageFunction  function)
{
  handler->function = function;
}

/** @} */