00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017 #include "utils/includes.h"
00018 #include <dbus/dbus.h>
00019
00020 #include "utils/common.h"
00021 #include "utils/eloop.h"
00022 #include "dbus_common.h"
00023 #include "dbus_common_i.h"
00024 #include "dbus_new.h"
00025 #include "dbus_old.h"
00026
00027
00028 #ifndef SIGPOLL
00029 #ifdef SIGIO
00030
00031
00032
00033
00034 #define SIGPOLL SIGIO
00035 #endif
00036 #endif
00037
00038
00039 static void dispatch_data(DBusConnection *con)
00040 {
00041 while (dbus_connection_get_dispatch_status(con) ==
00042 DBUS_DISPATCH_DATA_REMAINS)
00043 dbus_connection_dispatch(con);
00044 }
00045
00046
00057 static void dispatch_initial_dbus_messages(void *eloop_ctx, void *timeout_ctx)
00058 {
00059 DBusConnection *con = eloop_ctx;
00060 dispatch_data(con);
00061 }
00062
00063
00064 static void process_watch(struct wpas_dbus_priv *priv,
00065 DBusWatch *watch, eloop_event_type type)
00066 {
00067 dbus_connection_ref(priv->con);
00068
00069 priv->should_dispatch = 0;
00070
00071 if (type == EVENT_TYPE_READ)
00072 dbus_watch_handle(watch, DBUS_WATCH_READABLE);
00073 else if (type == EVENT_TYPE_WRITE)
00074 dbus_watch_handle(watch, DBUS_WATCH_WRITABLE);
00075 else if (type == EVENT_TYPE_EXCEPTION)
00076 dbus_watch_handle(watch, DBUS_WATCH_ERROR);
00077
00078 if (priv->should_dispatch) {
00079 dispatch_data(priv->con);
00080 priv->should_dispatch = 0;
00081 }
00082
00083 dbus_connection_unref(priv->con);
00084 }
00085
00086
00087 static void process_watch_exception(int sock, void *eloop_ctx, void *sock_ctx)
00088 {
00089 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_EXCEPTION);
00090 }
00091
00092
00093 static void process_watch_read(int sock, void *eloop_ctx, void *sock_ctx)
00094 {
00095 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_READ);
00096 }
00097
00098
00099 static void process_watch_write(int sock, void *eloop_ctx, void *sock_ctx)
00100 {
00101 process_watch(eloop_ctx, sock_ctx, EVENT_TYPE_WRITE);
00102 }
00103
00104
00105 static dbus_bool_t add_watch(DBusWatch *watch, void *data)
00106 {
00107 struct wpas_dbus_priv *priv = data;
00108 unsigned int flags;
00109 int fd;
00110
00111 if (!dbus_watch_get_enabled(watch))
00112 return TRUE;
00113
00114 flags = dbus_watch_get_flags(watch);
00115 fd = dbus_watch_get_unix_fd(watch);
00116
00117 eloop_register_sock(fd, EVENT_TYPE_EXCEPTION, process_watch_exception,
00118 priv, watch);
00119
00120 if (flags & DBUS_WATCH_READABLE) {
00121 eloop_register_sock(fd, EVENT_TYPE_READ, process_watch_read,
00122 priv, watch);
00123 }
00124 if (flags & DBUS_WATCH_WRITABLE) {
00125 eloop_register_sock(fd, EVENT_TYPE_WRITE, process_watch_write,
00126 priv, watch);
00127 }
00128
00129 dbus_watch_set_data(watch, priv, NULL);
00130
00131 return TRUE;
00132 }
00133
00134
00135 static void remove_watch(DBusWatch *watch, void *data)
00136 {
00137 unsigned int flags;
00138 int fd;
00139
00140 flags = dbus_watch_get_flags(watch);
00141 fd = dbus_watch_get_unix_fd(watch);
00142
00143 eloop_unregister_sock(fd, EVENT_TYPE_EXCEPTION);
00144
00145 if (flags & DBUS_WATCH_READABLE)
00146 eloop_unregister_sock(fd, EVENT_TYPE_READ);
00147 if (flags & DBUS_WATCH_WRITABLE)
00148 eloop_unregister_sock(fd, EVENT_TYPE_WRITE);
00149
00150 dbus_watch_set_data(watch, NULL, NULL);
00151 }
00152
00153
00154 static void watch_toggled(DBusWatch *watch, void *data)
00155 {
00156 if (dbus_watch_get_enabled(watch))
00157 add_watch(watch, data);
00158 else
00159 remove_watch(watch, data);
00160 }
00161
00162
00163 static void process_timeout(void *eloop_ctx, void *sock_ctx)
00164 {
00165 DBusTimeout *timeout = sock_ctx;
00166 dbus_timeout_handle(timeout);
00167 }
00168
00169
00170 static dbus_bool_t add_timeout(DBusTimeout *timeout, void *data)
00171 {
00172 struct wpas_dbus_priv *priv = data;
00173 if (!dbus_timeout_get_enabled(timeout))
00174 return TRUE;
00175
00176 eloop_register_timeout(0, dbus_timeout_get_interval(timeout) * 1000,
00177 process_timeout, priv, timeout);
00178
00179 dbus_timeout_set_data(timeout, priv, NULL);
00180
00181 return TRUE;
00182 }
00183
00184
00185 static void remove_timeout(DBusTimeout *timeout, void *data)
00186 {
00187 struct wpas_dbus_priv *priv = data;
00188 eloop_cancel_timeout(process_timeout, priv, timeout);
00189 dbus_timeout_set_data(timeout, NULL, NULL);
00190 }
00191
00192
00193 static void timeout_toggled(DBusTimeout *timeout, void *data)
00194 {
00195 if (dbus_timeout_get_enabled(timeout))
00196 add_timeout(timeout, data);
00197 else
00198 remove_timeout(timeout, data);
00199 }
00200
00201
00202 static void process_wakeup_main(int sig, void *signal_ctx)
00203 {
00204 struct wpas_dbus_priv *priv = signal_ctx;
00205
00206 if (sig != SIGPOLL || !priv->con)
00207 return;
00208
00209 if (dbus_connection_get_dispatch_status(priv->con) !=
00210 DBUS_DISPATCH_DATA_REMAINS)
00211 return;
00212
00213
00214 dbus_connection_ref(priv->con);
00215 dbus_connection_dispatch(priv->con);
00216 dbus_connection_unref(priv->con);
00217 }
00218
00219
00227 static void wakeup_main(void *data)
00228 {
00229 struct wpas_dbus_priv *priv = data;
00230
00231
00232 raise(SIGPOLL);
00233 priv->should_dispatch = 1;
00234 }
00235
00236
00243 static int integrate_with_eloop(struct wpas_dbus_priv *priv)
00244 {
00245 if (!dbus_connection_set_watch_functions(priv->con, add_watch,
00246 remove_watch, watch_toggled,
00247 priv, NULL) ||
00248 !dbus_connection_set_timeout_functions(priv->con, add_timeout,
00249 remove_timeout,
00250 timeout_toggled, priv,
00251 NULL)) {
00252 wpa_printf(MSG_ERROR, "dbus: Failed to set callback "
00253 "functions");
00254 return -1;
00255 }
00256
00257 if (eloop_register_signal(SIGPOLL, process_wakeup_main, priv))
00258 return -1;
00259 dbus_connection_set_wakeup_main_function(priv->con, wakeup_main,
00260 priv, NULL);
00261
00262 return 0;
00263 }
00264
00265
00266 static int wpas_dbus_init_common(struct wpas_dbus_priv *priv)
00267 {
00268 DBusError error;
00269 int ret = 0;
00270
00271
00272 dbus_error_init(&error);
00273 priv->con = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
00274 if (!priv->con) {
00275 wpa_printf(MSG_ERROR, "dbus: Could not acquire the system "
00276 "bus: %s - %s", error.name, error.message);
00277 ret = -1;
00278 }
00279 dbus_error_free(&error);
00280
00281 return ret;
00282 }
00283
00284
00285 static int wpas_dbus_init_common_finish(struct wpas_dbus_priv *priv)
00286 {
00287
00288 integrate_with_eloop(priv);
00289
00290
00291
00292
00293
00294
00295
00296
00297 eloop_register_timeout(0, 50, dispatch_initial_dbus_messages,
00298 priv->con, NULL);
00299
00300 return 0;
00301 }
00302
00303
00304 static void wpas_dbus_deinit_common(struct wpas_dbus_priv *priv)
00305 {
00306 if (priv->con) {
00307 eloop_cancel_timeout(dispatch_initial_dbus_messages,
00308 priv->con, NULL);
00309 dbus_connection_set_watch_functions(priv->con, NULL, NULL,
00310 NULL, NULL, NULL);
00311 dbus_connection_set_timeout_functions(priv->con, NULL, NULL,
00312 NULL, NULL, NULL);
00313 dbus_connection_unref(priv->con);
00314 }
00315
00316 os_free(priv);
00317 }
00318
00319
00320 struct wpas_dbus_priv * wpas_dbus_init(struct wpa_global *global)
00321 {
00322 struct wpas_dbus_priv *priv;
00323
00324 priv = os_zalloc(sizeof(*priv));
00325 if (priv == NULL)
00326 return NULL;
00327 priv->global = global;
00328
00329 if (wpas_dbus_init_common(priv) < 0) {
00330 wpas_dbus_deinit(priv);
00331 return NULL;
00332 }
00333
00334 #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
00335 if (wpas_dbus_ctrl_iface_init(priv) < 0) {
00336 wpas_dbus_deinit(priv);
00337 return NULL;
00338 }
00339 #endif
00340
00341 #ifdef CONFIG_CTRL_IFACE_DBUS
00342 if (wpa_supplicant_dbus_ctrl_iface_init(priv) < 0) {
00343 wpas_dbus_deinit(priv);
00344 return NULL;
00345 }
00346 #endif
00347
00348 if (wpas_dbus_init_common_finish(priv) < 0) {
00349 wpas_dbus_deinit(priv);
00350 return NULL;
00351 }
00352
00353 return priv;
00354 }
00355
00356
00357 void wpas_dbus_deinit(struct wpas_dbus_priv *priv)
00358 {
00359 if (priv == NULL)
00360 return;
00361
00362 #ifdef CONFIG_CTRL_IFACE_DBUS_NEW
00363 wpas_dbus_ctrl_iface_deinit(priv);
00364 #endif
00365
00366 #ifdef CONFIG_CTRL_IFACE_DBUS
00367
00368 #endif
00369
00370 wpas_dbus_deinit_common(priv);
00371 }