[PATCH 2/2] dbus: Do Not Coalesce Supplicant State Changes

Grant Erickson marathon96 at gmail.com
Fri Oct 21 20:22:37 EDT 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