Hi Leena,
On Thu, Oct 21, 2010 at 06:23:25PM +0530, [email protected] wrote:
> 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.
>
Very nice, I appreciate your detailed explanations as it makes my reviewer
life easier. Some minor comments on your patch:
> 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,
Trailing whitespaces.
> + 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);
> +
This line is over 80 characters.
> + 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)
Trailing whitespace.
> +{
> + GSupplicantInterface *interface = user_data;
> +
Trailing whitspace here.
> + if (iter) {
Here I'd prefer if you would just return if iter is NULL, and then go on with
the code block below.
> + 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)
Trailing whitespace.
> + callback_network_added(network);
> + }
Trailing whitspace.
> +}
> +
> +static void scan_bss_data(const char *key, DBusMessageIter *iter,
> + void *user_data)
> +{
> + GSupplicantInterface *interface = user_data;
> +
Trailing whitespace (There are more trailing whitespaces, please fix all
them).
> + if (iter)
> + supplicant_dbus_array_foreach(iter, scan_network_update,
> interface);
> +
> + if (interface->scan_callback != NULL) {
No need for brackets here.
> + interface->scan_callback(0, interface,
> + interface->scan_data);
You could have this one here in one single line.
> + }
> +
> + 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);
>
Line is over 80 chars.
Moreover, here as well I'd prefer:
if (success == FALSE) {
if (interface->scan_callback != NULL)
interface->scan_callback(-EIO, interface,
interface->scan_data);
interface->scan_callback = NULL;
interface->scan_data = NULL;
return;
}
supplicant_dbus_property_get();
> + } 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;
> }
This chunk is irrelevant to this patch.
> 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);
This is actually a fix for a separate bug. I applied it to our tree already,
please don't include it with your next patch revision.
Cheers,
Samuel.
--
Intel Open Source Technology Centre
http://oss.intel.com/
_______________________________________________
connman mailing list
[email protected]
http://lists.connman.net/listinfo/connman