dbus: Rename old D-Bus API files to include "_old"
[hostap-gosc2009.git] / wpa_supplicant / dbus / dbus_common.c
blob69277ab0ad21aa323cf4a7d407c51ed3d303235a
1 /*
2 * wpa_supplicant D-Bus control interface - common functionality
3 * Copyright (c) 2006, Dan Williams <dcbw@redhat.com> and Red Hat, Inc.
4 * Copyright (c) 2009, Witold Sowa <witold.sowa@gmail.com>
5 * Copyright (c) 2009, Jouni Malinen <j@w1.fi>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * Alternatively, this software may be distributed under the terms of BSD
12 * license.
14 * See README and COPYING for more details.
17 #include "utils/includes.h"
18 #include <dbus/dbus.h>
20 #include "utils/common.h"
21 #include "utils/eloop.h"
22 #include "dbus_common.h"
23 #include "dbus_common_i.h"
24 #include "dbus_new.h"
25 #include "dbus_old.h"
28 /**
29 * dispatch_initial_dbus_messages - Dispatch initial dbus messages after
30 * claiming bus name
31 * @eloop_ctx: the DBusConnection to dispatch on
32 * @timeout_ctx: unused
34 * If clients are quick to notice that service claimed its bus name,
35 * there may have been messages that came in before initialization was
36 * all finished. Dispatch those here.
38 static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
40 DBusConnection *con = eloop_ctx;
42 while (dbus_connection_get_dispatch_status(con) ==
43 DBUS_DISPATCH_DATA_REMAINS)
44 dbus_connection_dispatch(con);
48 static void process_watch(struct wpas_dbus_priv *priv,
49 DBusWatch *watch, eloop_event_type type)
51 dbus_connection_ref(priv->con);
53 priv->should_dispatch = 0;
55 if (type == EVENT_TYPE_READ)
56 dbus_watch_handle(watch, DBUS_WATCH_READABLE);
57 else if (type == EVENT_TYPE_WRITE)
58 dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
59 else if (type == EVENT_TYPE_EXCEPTION)
60 dbus_watch_handle(watch, DBUS_WATCH_ERROR);
62 if (priv->should_dispatch) {
63 while (dbus_connection_get_dispatch_status(priv->con) ==
64 DBUS_DISPATCH_DATA_REMAINS)
65 dbus_connection_dispatch(priv->con);
66 priv->should_dispatch = 0;
69 dbus_connection_unref(priv->con);
73 static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
75 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
79 static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
81 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
85 static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
87 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
91 static void connection_setup_add_watch(struct wpas_dbus_priv *priv,
92 DBusWatch *watch)
94 unsigned int flags;
95 int fd;
97 if (!dbus_watch_get_enabled(watch))
98 return;
100 flags = dbus_watch_get_flags(watch);
101 fd = dbus_watch_get_unix_fd(watch);
103 eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,
104 priv, watch);
106 if (flags & DBUS_WATCH_READABLE) {
107 eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
108 priv, watch);
110 if (flags & DBUS_WATCH_WRITABLE) {
111 eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
112 priv, watch);
115 dbus_watch_set_data(watch, priv, NULL);
119 static void connection_setup_remove_watch(struct wpas_dbus_priv *priv,
120 DBusWatch *watch)
122 unsigned int flags;
123 int fd;
125 flags = dbus_watch_get_flags(watch);
126 fd = dbus_watch_get_unix_fd(watch);
128 eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
130 if (flags & DBUS_WATCH_READABLE)
131 eloop_unregister_sock(fd, EVENT_TYPE_READ);
132 if (flags & DBUS_WATCH_WRITABLE)
133 eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
135 dbus_watch_set_data(watch, NULL, NULL);
139 static dbus_bool_t add_watch(DBusWatch *watch, void *data)
141 connection_setup_add_watch(data, watch);
142 return TRUE;
146 static void remove_watch(DBusWatch *watch, void *data)
148 connection_setup_remove_watch(data, watch);
152 static void watch_toggled(DBusWatch *watch, void *data)
154 if (dbus_watch_get_enabled(watch))
155 add_watch(watch, data);
156 else
157 remove_watch(watch, data);
161 static void process_timeout(void *eloop_ctx, void *sock_ctx)
163 DBusTimeout *timeout = sock_ctx;
165 dbus_timeout_handle(timeout);
169 static void connection_setup_add_timeout(struct wpas_dbus_priv *priv,
170 DBusTimeout *timeout)
172 if (!dbus_timeout_get_enabled(timeout))
173 return;
175 eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
176 process_timeout, priv, timeout);
178 dbus_timeout_set_data(timeout, priv, NULL);
182 static void connection_setup_remove_timeout(struct wpas_dbus_priv *priv,
183 DBusTimeout *timeout)
185 eloop_cancel_timeout(process_timeout, priv, timeout);
186 dbus_timeout_set_data(timeout, NULL, NULL);
190 static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
192 if (!dbus_timeout_get_enabled(timeout))
193 return TRUE;
195 connection_setup_add_timeout(data, timeout);
197 return TRUE;
201 static void remove_timeout(DBusTimeout *timeout, void *data)
203 connection_setup_remove_timeout(data, timeout);
207 static void timeout_toggled(DBusTimeout *timeout, void *data)
209 if (dbus_timeout_get_enabled(timeout))
210 add_timeout(timeout, data);
211 else
212 remove_timeout(timeout, data);
216 static void process_wakeup_main(int sig, void *signal_ctx)
218 struct wpas_dbus_priv *priv = signal_ctx;
220 if (sig != SIGPOLL || !priv->con)
221 return;
223 if (dbus_connection_get_dispatch_status(priv->con) !=
224 DBUS_DISPATCH_DATA_REMAINS)
225 return;
227 /* Only dispatch once - we do not want to starve other events */
228 dbus_connection_ref(priv->con);
229 dbus_connection_dispatch(priv->con);
230 dbus_connection_unref(priv->con);
235 * wakeup_main - Attempt to wake our mainloop up
236 * @data: dbus control interface private data
238 * Try to wake up the main eloop so it will process
239 * dbus events that may have happened.
241 static void wakeup_main(void *data)
243 struct wpas_dbus_priv *priv = data;
245 /* Use SIGPOLL to break out of the eloop select() */
246 raise(SIGPOLL);
247 priv->should_dispatch = 1;
252 * connection_setup_wakeup_main - Tell dbus about our wakeup_main function
253 * @priv: dbus control interface private data
254 * Returns: 0 on success, -1 on failure
256 * Register our wakeup_main handler with dbus
258 static int connection_setup_wakeup_main(struct wpas_dbus_priv *priv)
260 if (eloop_register_signal(SIGPOLL, process_wakeup_main, priv))
261 return -1;
263 dbus_connection_set_wakeup_main_function(priv->con, wakeup_main,
264 priv, NULL);
266 return 0;
271 * integrate_with_eloop - Register our mainloop integration with dbus
272 * @connection: connection to the system message bus
273 * @priv: a dbus control interface data structure
274 * Returns: 0 on success, -1 on failure
276 * We register our mainloop integration functions with dbus here.
278 static int integrate_with_eloop(struct wpas_dbus_priv *priv)
280 if (!dbus_connection_set_watch_functions(priv->con, add_watch,
281 remove_watch, watch_toggled,
282 priv, NULL)) {
283 perror("dbus_connection_set_watch_functions[dbus]");
284 wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
285 return -1;
288 if (!dbus_connection_set_timeout_functions(priv->con, add_timeout,
289 remove_timeout,
290 timeout_toggled, priv,
291 NULL)) {
292 perror("dbus_connection_set_timeout_functions[dbus]");
293 wpa_printf(MSG_ERROR, "Not enough memory to set up dbus.");
294 return -1;
297 if (connection_setup_wakeup_main(priv) < 0) {
298 perror("connection_setup_wakeup_main[dbus]");
299 wpa_printf(MSG_ERROR, "Could not setup main wakeup function.");
300 return -1;
303 return 0;
307 static int wpas_dbus_init_common(struct wpas_dbus_priv *priv)
309 DBusError error;
311 /* Get a reference to the system bus */
312 dbus_error_init(&error);
313 priv->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
314 dbus_error_free(&error);
315 if (!priv->con) {
316 wpa_printf(MSG_ERROR, "dbus: Could not acquire the system "
317 "bus: %s", strerror(errno));
318 return -1;
321 return 0;
325 static int wpas_dbus_init_common_finish(struct wpas_dbus_priv *priv)
327 /* Tell dbus about our mainloop integration functions */
328 integrate_with_eloop(priv);
331 * Dispatch initial DBus messages that may have come in since the bus
332 * name was claimed above. Happens when clients are quick to notice the
333 * service.
335 * FIXME: is there a better solution to this problem?
337 eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
338 priv->con, NULL);
340 return 0;
344 static void wpas_dbus_deinit_common(struct wpas_dbus_priv *priv)
346 if (priv->con) {
347 eloop_cancel_timeout(dispatch_initial_dbus_messages,
348 priv->con, NULL);
349 dbus_connection_set_watch_functions(priv->con, NULL, NULL,
350 NULL, NULL, NULL);
351 dbus_connection_set_timeout_functions(priv->con, NULL, NULL,
352 NULL, NULL, NULL);
353 dbus_connection_unref(priv->con);
356 os_free(priv);
360 struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global)
362 struct wpas_dbus_priv *priv;
364 priv = os_zalloc(sizeof(*priv));
365 if (priv == NULL)
366 return NULL;
367 priv->global = global;
369 if (wpas_dbus_init_common(priv) < 0) {
370 wpas_dbus_deinit(priv);
371 return NULL;
374 #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
375 if (wpas_dbus_ctrl_iface_init(priv) < 0) {
376 wpas_dbus_deinit(priv);
377 return NULL;
379 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
381 #ifdef CONFIG_CTRL_IFACE_DBUS
382 if (wpa_supplicant_dbus_ctrl_iface_init(priv) < 0) {
383 wpas_dbus_deinit(priv);
384 return NULL;
386 #endif /* CONFIG_CTRL_IFACE_DBUS */
388 if (wpas_dbus_init_common_finish(priv) < 0) {
389 wpas_dbus_deinit(priv);
390 return NULL;
393 return priv;
397 void wpas_dbus_deinit(struct wpas_dbus_priv *priv)
399 if (priv == NULL)
400 return;
402 #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
403 wpas_dbus_ctrl_iface_deinit(priv);
404 #endif /* CONFIG_CTRL_IFACE_DBUS_NEW */
406 #ifdef CONFIG_CTRL_IFACE_DBUS
407 /* TODO: is any deinit needed? */
408 #endif /* CONFIG_CTRL_IFACE_DBUS */
410 wpas_dbus_deinit_common(priv);