[PATCH 2/2] dbus: Do Not Coalesce Supplicant State Changes
Grant Erickson
marathon96
Fri Oct 21 17:22:37 PDT 2011
To ensure that higher-level network managers receive all state changes, do not coalesce
supplicant state changes. Rather, make state change signals synchronous.
Signed-off-by: Grant Erickson <marathon96 at gmail.com>
---
wpa_supplicant/dbus/dbus_new.c | 63 +++++++++++++++++++-------
wpa_supplicant/dbus/dbus_new.h | 3 +-
wpa_supplicant/dbus/dbus_new_handlers_wps.c | 8 ++--
wpa_supplicant/dbus/dbus_new_helpers.c | 61 ++++++++++++++++++++------
wpa_supplicant/dbus/dbus_new_helpers.h | 10 +++-
wpa_supplicant/notify.c | 2 +-
6 files changed, 107 insertions(+), 40 deletions(-)
diff --git a/wpa_supplicant/dbus/dbus_new.c b/wpa_supplicant/dbus/dbus_new.c
index 8153880..6933739 100644
--- a/wpa_supplicant/dbus/dbus_new.c
+++ b/wpa_supplicant/dbus/dbus_new.c
@@ -398,8 +398,8 @@ void wpas_dbus_signal_network_enabled_changed(struct wpa_supplicant *wpa_s,
"%s/" WPAS_DBUS_NEW_NETWORKS_PART "/%d",
wpa_s->dbus_new_path, ssid->id);
- wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
- WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
+ wpa_dbus_queue_property_changed(wpa_s->global->dbus, path,
+ WPAS_DBUS_NEW_IFACE_NETWORK, "Enabled");
}
@@ -1452,6 +1452,35 @@ void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
/**
+ * wpas_dbus_signal_state_changed - Signals change of state property
+ * @wpa_s: %wpa_supplicant network interface data
+ *
+ * Sends ProertyChanged signals immediately with path, interface and
+ * arguments for the supplicant state property. This is sent
+ * immediately so that supplicant state changes are NOT coaslesced
+ * which can lead to problems in higher-level network managers which
+ * depend on seeing all, specific state changes for correct operation.
+ */
+void wpas_dbus_signal_state_changed(struct wpa_supplicant *wpa_s)
+{
+ struct wpa_dbus_object_desc *obj_desc = NULL;
+
+ if (wpa_s->dbus_new_path == NULL)
+ return; /* Skip signal since D-Bus setup is not yet ready */
+
+ obj_desc = wpa_dbus_mark_property_changed(wpa_s->global->dbus,
+ wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_INTERFACE,
+ "State");
+ if (!obj_desc)
+ return;
+
+ wpa_dbus_flush_object_changed_properties(wpa_s->global->dbus->con,
+ obj_desc->path);
+}
+
+
+/**
* wpas_dbus_signal_prop_changed - Signals change of property
* @wpa_s: %wpa_supplicant network interface data
* @property: indicates which property has changed
@@ -1462,7 +1491,7 @@ void wpas_dbus_signal_p2p_wps_failed(struct wpa_supplicant *wpa_s,
void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
enum wpas_dbus_prop property)
{
- char *prop;
+ const char *prop;
if (wpa_s->dbus_new_path == NULL)
return; /* Skip signal since D-Bus setup is not yet ready */
@@ -1495,9 +1524,9 @@ void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
return;
}
- wpa_dbus_mark_property_changed(wpa_s->global->dbus,
- wpa_s->dbus_new_path,
- WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
+ wpa_dbus_queue_property_changed(wpa_s->global->dbus,
+ wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_INTERFACE, prop);
}
@@ -1552,8 +1581,8 @@ void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
"%s/" WPAS_DBUS_NEW_BSSIDS_PART "/%u",
wpa_s->dbus_new_path, id);
- wpa_dbus_mark_property_changed(wpa_s->global->dbus, path,
- WPAS_DBUS_NEW_IFACE_BSS, prop);
+ wpa_dbus_queue_property_changed(wpa_s->global->dbus, path,
+ WPAS_DBUS_NEW_IFACE_BSS, prop);
}
@@ -1565,9 +1594,9 @@ void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
*/
void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
{
- wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
- WPAS_DBUS_NEW_INTERFACE,
- "DebugLevel");
+ wpa_dbus_queue_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
+ WPAS_DBUS_NEW_INTERFACE,
+ "DebugLevel");
}
@@ -1579,9 +1608,9 @@ void wpas_dbus_signal_debug_level_changed(struct wpa_global *global)
*/
void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
{
- wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
- WPAS_DBUS_NEW_INTERFACE,
- "DebugTimestamp");
+ wpa_dbus_queue_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
+ WPAS_DBUS_NEW_INTERFACE,
+ "DebugTimestamp");
}
@@ -1593,9 +1622,9 @@ void wpas_dbus_signal_debug_timestamp_changed(struct wpa_global *global)
*/
void wpas_dbus_signal_debug_show_keys_changed(struct wpa_global *global)
{
- wpa_dbus_mark_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
- WPAS_DBUS_NEW_INTERFACE,
- "DebugShowKeys");
+ wpa_dbus_queue_property_changed(global->dbus, WPAS_DBUS_NEW_PATH,
+ WPAS_DBUS_NEW_INTERFACE,
+ "DebugShowKeys");
}
diff --git a/wpa_supplicant/dbus/dbus_new.h b/wpa_supplicant/dbus/dbus_new.h
index 080000c..a2594df 100644
--- a/wpa_supplicant/dbus/dbus_new.h
+++ b/wpa_supplicant/dbus/dbus_new.h
@@ -123,6 +123,7 @@ void wpas_dbus_ctrl_iface_deinit(struct wpas_dbus_priv *iface);
int wpas_dbus_register_interface(struct wpa_supplicant *wpa_s);
int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s);
+void wpas_dbus_signal_state_changed(struct wpa_supplicant *wpa_s);
void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
enum wpas_dbus_prop property);
void wpas_dbus_bss_signal_prop_changed(struct wpa_supplicant *wpa_s,
@@ -218,7 +219,7 @@ static inline int wpas_dbus_unregister_interface(struct wpa_supplicant *wpa_s)
return 0;
}
-#define wpas_dbus_signal_state_changed(w, n, o) do { } while (0)
+#define wpas_dbus_signal_state_changed(w) do { } while (0)
static inline void wpas_dbus_signal_prop_changed(struct wpa_supplicant *wpa_s,
enum wpas_dbus_prop property)
diff --git a/wpa_supplicant/dbus/dbus_new_handlers_wps.c b/wpa_supplicant/dbus/dbus_new_handlers_wps.c
index d8b74d0..a273005 100644
--- a/wpa_supplicant/dbus/dbus_new_handlers_wps.c
+++ b/wpa_supplicant/dbus/dbus_new_handlers_wps.c
@@ -326,10 +326,10 @@ dbus_bool_t wpas_dbus_setter_process_credentials(DBusMessageIter *iter,
wpa_s->conf->wps_cred_processing = (process_credentials ? 2 : 1);
if ((wpa_s->conf->wps_cred_processing != 1) != old_pc)
- wpa_dbus_mark_property_changed(wpa_s->global->dbus,
- wpa_s->dbus_new_path,
- WPAS_DBUS_NEW_IFACE_WPS,
- "ProcessCredentials");
+ wpa_dbus_queue_property_changed(wpa_s->global->dbus,
+ wpa_s->dbus_new_path,
+ WPAS_DBUS_NEW_IFACE_WPS,
+ "ProcessCredentials");
return TRUE;
}
diff --git a/wpa_supplicant/dbus/dbus_new_helpers.c b/wpa_supplicant/dbus/dbus_new_helpers.c
index 342ad2d..ba7ce12 100644
--- a/wpa_supplicant/dbus/dbus_new_helpers.c
+++ b/wpa_supplicant/dbus/dbus_new_helpers.c
@@ -752,13 +752,17 @@ void wpa_dbus_flush_all_changed_properties(DBusConnection *con)
* containing properties marked as changed, sends a PropertiesChanged signal
* containing names and new values of properties that have changed.
*
- * You need to call this function after wpa_dbus_mark_property_changed()
- * if you want to send PropertiesChanged signal immediately (i.e., without
- * waiting timeout to expire). PropertiesChanged signal for an object is sent
- * automatically short time after first marking property as changed. All
- * PropertiesChanged signals are sent automatically after responding on DBus
- * message, so if you marked a property changed as a result of DBus call
- * (e.g., param setter), you usually do not need to call this function.
+ * You need to call this function after
+ * wpa_dbus_mark_property_changed() to send the PropertyChanged signal
+ * or after wpa_dbus_queue_property_changed() if you want to send
+ * PropertiesChanged signal immediately (i.e., without waiting timeout
+ * to expire).
+ *
+ * PropertiesChanged signal for an object is sent automatically short
+ * time after first marking property as changed. All PropertiesChanged
+ * signals are sent automatically after responding on DBus message, so
+ * if you marked a property changed as a result of DBus call (e.g.,
+ * param setter), you usually do not need to call this function.
*/
void wpa_dbus_flush_object_changed_properties(DBusConnection *con,
const char *path)
@@ -788,11 +792,12 @@ void wpa_dbus_flush_object_changed_properties(DBusConnection *con,
/**
- * wpa_dbus_mark_property_changed - Mark a property as changed and
+ * wpa_dbus_mark_property_changed - Mark a property as changed
* @iface: dbus priv struct
* @path: path to DBus object which property has changed
* @interface: interface containing changed property
* @property: property name which has changed
+ * Returns: A pointer to the private data for the object on success.
*
* Iterates over all properties registered with an object and marks the one
* given in parameters as changed. All parameters registered for an object
@@ -800,23 +805,24 @@ void wpa_dbus_flush_object_changed_properties(DBusConnection *con,
* PropertiesChanged signal when function
* wpa_dbus_flush_object_changed_properties() is called.
*/
-void wpa_dbus_mark_property_changed(struct wpas_dbus_priv *iface,
- const char *path, const char *interface,
- const char *property)
+struct wpa_dbus_object_desc *
+wpa_dbus_mark_property_changed(struct wpas_dbus_priv *iface,
+ const char *path, const char *interface,
+ const char *property)
{
struct wpa_dbus_object_desc *obj_desc = NULL;
const struct wpa_dbus_property_desc *dsc;
int i = 0;
if (iface == NULL)
- return;
+ return NULL;
dbus_connection_get_object_path_data(iface->con, path,
(void **) &obj_desc);
if (!obj_desc) {
wpa_printf(MSG_ERROR, "dbus: wpa_dbus_property_changed: "
"could not obtain object's private data: %s", path);
- return;
+ return NULL;
}
for (dsc = obj_desc->properties; dsc && dsc->dbus_property; dsc++, i++)
@@ -830,9 +836,36 @@ void wpa_dbus_mark_property_changed(struct wpas_dbus_priv *iface,
if (!dsc || !dsc->dbus_property) {
wpa_printf(MSG_ERROR, "dbus: wpa_dbus_property_changed: "
"no property %s in object %s", property, path);
- return;
+ return NULL;
}
+ return obj_desc;
+}
+
+/**
+ * wpa_dbus_queue_property_changed - Mark a property as changed and send it
+ * @iface: dbus priv struct
+ * @path: path to DBus object which property has changed
+ * @interface: interface containing changed property
+ * @property: property name which has changed
+ *
+ * Iterates over all properties registered with an object and marks the one
+ * given in parameters as changed. All parameters registered for an object
+ * within a single interface will be aggregated together and sent in one
+ * PropertiesChanged signal when function
+ * wpa_dbus_flush_object_changed_properties() is called.
+ */
+void wpa_dbus_queue_property_changed(struct wpas_dbus_priv *iface,
+ const char *path, const char *interface,
+ const char *property)
+{
+ struct wpa_dbus_object_desc *obj_desc;
+
+ obj_desc = wpa_dbus_mark_property_changed(iface, path, interface,
+ property);
+ if (!obj_desc)
+ return;
+
if (!eloop_is_timeout_registered(flush_object_timeout_handler,
iface->con, obj_desc->path)) {
eloop_register_timeout(0, WPA_DBUS_SEND_PROP_CHANGED_TIMEOUT,
diff --git a/wpa_supplicant/dbus/dbus_new_helpers.h b/wpa_supplicant/dbus/dbus_new_helpers.h
index 87f4da5..c50ec58 100644
--- a/wpa_supplicant/dbus/dbus_new_helpers.h
+++ b/wpa_supplicant/dbus/dbus_new_helpers.h
@@ -136,9 +136,13 @@ void wpa_dbus_flush_all_changed_properties(DBusConnection *con);
void wpa_dbus_flush_object_changed_properties(DBusConnection *con,
const char *path);
-void wpa_dbus_mark_property_changed(struct wpas_dbus_priv *iface,
- const char *path, const char *interface,
- const char *property);
+struct wpa_dbus_object_desc * wpa_dbus_mark_property_changed(
+ struct wpas_dbus_priv *iface,
+ const char *path, const char *interface,
+ const char *property);
+void wpa_dbus_queue_property_changed(struct wpas_dbus_priv *iface,
+ const char *path, const char *interface,
+ const char *property);
DBusMessage * wpa_dbus_introspect(DBusMessage *message,
struct wpa_dbus_object_desc *obj_dsc);
diff --git a/wpa_supplicant/notify.c b/wpa_supplicant/notify.c
index 75b9acf..cb5f041 100644
--- a/wpa_supplicant/notify.c
+++ b/wpa_supplicant/notify.c
@@ -83,7 +83,7 @@ void wpas_notify_state_changed(struct wpa_supplicant *wpa_s,
old_state);
/* notify the new DBus API */
- wpas_dbus_signal_prop_changed(wpa_s, WPAS_DBUS_PROP_STATE);
+ wpas_dbus_signal_state_changed(wpa_s);
#ifdef CONFIG_P2P
if (new_state == WPA_COMPLETED)
--
1.7.6.4
More information about the Hostap
mailing list