Kindly review the patch for below connman bugs:
http://bugs.meego.com/show_bug.cgi?id=8363
http://bugs.meego.com/show_bug.cgi?id=8324

Steps to reproduce: Launch connmand with -P wifi_legacy, connect to a WiFi AP, 
then disconnect/remove, WiFi APs will disappear.
This bug is also seen randomly even without disconnecting/removing networks 
after a scan is complete.

Analysis:
When connmand is started without the wifi_legacy plugin, the new wifi plugin is 
loaded. When a scan is initiated by the wifi plugin, 
connman_device_set_scanning() is invoked with scanning set to true. This will 
in turn mark all the current networks as unavailable. Now when scanning is 
over, gsupplicant library will invoke the scan_callback of the wifi plugin. But 
the current BSSs data returned by scan is not obtained and also the networks 
are not updated/marked as available. The wifi plugin's scan_callback will now 
invoke connman_device_set_scanning() with scanning set to false. This will in 
turn cleanup and remove all networks which are not connected and unavailable. 
As a result the connman_networks are removed and the `test-connman srrvices` 
will display an empty list.

Solution:
On getting a signal_scan_done if the scan is successful, fetching the scan BSSs 
data and updating the existing connman network list will fix this issue. The 
patch does the below:

- Add a new API supplicant_dbus_property_get to gsupplicant library which will 
get the property for the specified method name. This is required to get the 
BSSs data. In future this API can also be used for other properties methods.

- scan_bss_data () and scan_network_update () functions to get the BSSs data 
and update existing network list respectively.

- scan_network_update () invokes wifi plugin's network_added() callback for 
existing connman network list which will update the network data and also set 
them back as available.

- Modify wifi plugin's network_added() to look for existing network based on 
the identifier and not path.

Patch:
------
 gsupplicant/dbus.c       |   82 ++++++++++++++++++++++++++++++++++++++++++++++
 gsupplicant/dbus.h       |    5 +++
 gsupplicant/supplicant.c |   64 +++++++++++++++++++++++++++++-------
 plugins/wifi.c           |    2 +-
 4 files changed, 140 insertions(+), 13 deletions(-)

diff --git a/gsupplicant/dbus.c b/gsupplicant/dbus.c
index 23593f4..2d27ff9 100644
--- a/gsupplicant/dbus.c
+++ b/gsupplicant/dbus.c
@@ -182,6 +182,88 @@ int supplicant_dbus_property_get_all(const char *path, 
const char *interface,
        return 0;
 }
 
+static void property_get_reply(DBusPendingCall *call, void *user_data)
+{
+       struct property_get_data *data = user_data;
+       DBusMessage *reply;
+       DBusMessageIter iter;
+
+       reply = dbus_pending_call_steal_reply(call);
+
+       if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
+               goto done;
+
+       if (dbus_message_iter_init(reply, &iter) == FALSE)
+               goto done;
+
+       if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) {
+               DBusMessageIter variant;
+
+               dbus_message_iter_recurse(&iter, &variant);
+
+               if (data->function != NULL)
+                       data->function(NULL, &variant, data->user_data);
+       }
+done:
+       dbus_message_unref(reply);
+
+       dbus_pending_call_unref(call);
+}
+
+int supplicant_dbus_property_get(const char *path, const char *interface,
+                               const char *method,  
+                               supplicant_dbus_property_function function,
+                                                       void *user_data)
+{
+       struct property_get_data *data;
+       DBusMessage *message;
+       DBusPendingCall *call;
+
+       if (connection == NULL)
+               return -EINVAL;
+
+       if (path == NULL || interface == NULL || method == NULL)
+               return -EINVAL;
+
+       data = dbus_malloc0(sizeof(*data));
+       if (data == NULL)
+               return -ENOMEM;
+
+       message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
+                                       DBUS_INTERFACE_PROPERTIES, "Get");
+       if (message == NULL) {
+               dbus_free(data);
+               return -ENOMEM;
+       }
+
+       dbus_message_set_auto_start(message, FALSE);
+
+       dbus_message_append_args(message, DBUS_TYPE_STRING, &interface, 
DBUS_TYPE_STRING, &method, NULL);
+
+       if (dbus_connection_send_with_reply(connection, message,
+                                               &call, TIMEOUT) == FALSE) {
+               dbus_message_unref(message);
+               dbus_free(data);
+               return -EIO;
+       }
+
+       if (call == NULL) {
+               dbus_message_unref(message);
+               dbus_free(data);
+               return -EIO;
+       }
+
+       data->function = function;
+       data->user_data = user_data;
+
+       dbus_pending_call_set_notify(call, property_get_reply,
+                                                       data, dbus_free);
+
+       dbus_message_unref(message);
+
+       return 0;
+}
+
 struct property_set_data {
        supplicant_dbus_result_function function;
        void *user_data;
diff --git a/gsupplicant/dbus.h b/gsupplicant/dbus.h
index 254b93e..642e8b1 100644
--- a/gsupplicant/dbus.h
+++ b/gsupplicant/dbus.h
@@ -51,6 +51,11 @@ int supplicant_dbus_property_get_all(const char *path, const 
char *interface,
                                supplicant_dbus_property_function function,
                                                        void *user_data);
 
+int supplicant_dbus_property_get(const char *path, const char *interface,
+                               const char *method,
+                               supplicant_dbus_property_function function,
+                                                       void *user_data);
+
 int supplicant_dbus_property_set(const char *path, const char *interface,
                                const char *key, const char *signature,
                                supplicant_dbus_setup_function setup,
diff --git a/gsupplicant/supplicant.c b/gsupplicant/supplicant.c
index 2670c94..a2a188b 100644
--- a/gsupplicant/supplicant.c
+++ b/gsupplicant/supplicant.c
@@ -1300,6 +1300,46 @@ static void interface_property(const char *key, 
DBusMessageIter *iter,
                                key, dbus_message_iter_get_arg_type(iter));
 }
 
+static void scan_network_update(DBusMessageIter *iter, void *user_data) 
+{
+       GSupplicantInterface *interface = user_data;
+       
+       if (iter) {
+               GSupplicantNetwork *network;
+               char *path;
+
+               dbus_message_iter_get_basic(iter, &path);
+
+               if (path == NULL)
+                       return;
+
+               if (g_strcmp0(path, "/") == 0)
+                       return;
+
+               /* Update the network details based on scan BSS data */
+               network = g_hash_table_lookup(interface->bss_mapping, path);
+               if (network != NULL) 
+                       callback_network_added(network);
+       } 
+}
+
+static void scan_bss_data(const char *key, DBusMessageIter *iter,
+                               void *user_data)
+{
+       GSupplicantInterface *interface = user_data;
+       
+       if (iter) 
+               supplicant_dbus_array_foreach(iter, scan_network_update, 
interface);
+       
+       if (interface->scan_callback != NULL) {
+               interface->scan_callback(0, interface,
+                                       interface->scan_data);
+       }
+
+       interface->scan_callback = NULL;
+       interface->scan_data = NULL;
+}
+
 static GSupplicantInterface *interface_alloc(const char *path)
 {
        GSupplicantInterface *interface;
@@ -1511,18 +1551,19 @@ static void signal_scan_done(const char *path, 
DBusMessageIter *iter)
 
        dbus_message_iter_get_basic(iter, &success);
 
-       if (interface->scan_callback != NULL) {
-               int result = 0;
-
-               if (success == FALSE)
-                       result = -EIO;
-
-               interface->scan_callback(result, interface,
-                                               interface->scan_data);
+       /* If scan is successful, get the scanned BSSs and update the network
+        * details accordingly else return -EIO
+        */
+       if (success) {
+               supplicant_dbus_property_get(path, SUPPLICANT_INTERFACE 
".Interface", 
+                                               "BSSs", scan_bss_data, 
interface);
+       } else {
+               if (interface->scan_callback != NULL)
+                       interface->scan_callback(-EIO, interface,
+                                                       interface->scan_data);
+               interface->scan_callback = NULL;
+               interface->scan_data = NULL;
        }
-
-       interface->scan_callback = NULL;
-       interface->scan_data = NULL;
 }
 
 static void signal_bss_added(const char *path, DBusMessageIter *iter)
@@ -1769,7 +1810,6 @@ static void interface_get_result(const char *error,
        SUPPLICANT_DBG("");
 
        if (error != NULL) {
-               g_warning("error %s", error);
                err = -EIO;
                goto create;
        }
diff --git a/plugins/wifi.c b/plugins/wifi.c
index 8dafe9f..90acc5e 100644
--- a/plugins/wifi.c
+++ b/plugins/wifi.c
@@ -430,7 +430,7 @@ static void network_added(GSupplicantNetwork 
*supplicant_network)
 
        ssid = g_supplicant_network_get_ssid(supplicant_network, &ssid_len);
 
-       network = connman_device_get_network(wifi->device, path);
+       network = connman_device_get_network(wifi->device, identifier);
 
        if (network == NULL) {
                network = connman_network_create(identifier,
------

Please do not print this email unless it is absolutely necessary. 

The information contained in this electronic message and any attachments to 
this message are intended for the exclusive use of the addressee(s) and may 
contain proprietary, confidential or privileged information. If you are not the 
intended recipient, you should not disseminate, distribute or copy this e-mail. 
Please notify the sender immediately and destroy all copies of this message and 
any attachments. 

WARNING: Computer viruses can be transmitted via email. The recipient should 
check this email and any attachments for the presence of viruses. The company 
accepts no liability for any damage caused by any virus transmitted by this 
email. 

www.wipro.com
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman

Reply via email to