Commit 8e1ed80a authored by Zeeshan Ali's avatar Zeeshan Ali

wifi: Tell wpa_supplicant to keep scanning

It seems by default, wpa_supplicant won't keep a list of BSS around but
only if it has done a scan recently. This means we currently end up with
very bad accuracy since we only send out the ESSID of the currently
connected WiFi (if any).

To fix this, we'll now tell wpa_supplicant to start a scan when the source is
started. We keep doing that continuously if accuracy is street level or higher,
but wait 5 minutues between scans if requested accuracy is lower than that.

Fixes #91.
parent f871ce1d
Pipeline #13222 passed with stage
in 3 minutes and 38 seconds
......@@ -28,6 +28,11 @@
#include "gclue-error.h"
#include "gclue-mozilla.h"
/* Since this is only used for city-level accuracy, 5 minutes betweeen each
* scan is more than enough.
*/
#define WIFI_SCAN_TIMEOUT 300
/**
* SECTION:gclue-wifi
* @short_description: WiFi-based geolocation
......@@ -49,8 +54,10 @@ struct _GClueWifiPrivate {
gulong bss_added_id;
gulong bss_removed_id;
gulong scan_done_id;
guint refresh_timeout;
guint scan_timeout;
GClueAccuracyLevel accuracy_level;
};
......@@ -82,6 +89,14 @@ G_DEFINE_TYPE (GClueWifi, gclue_wifi, GCLUE_TYPE_WEB_SOURCE)
static void
disconnect_bss_signals (GClueWifi *wifi);
static void
on_scan_call_done (GObject *source_object,
GAsyncResult *res,
gpointer user_data);
static void
on_scan_done (WPAInterface *object,
gboolean success,
gpointer user_data);
static void
gclue_wifi_finalize (GObject *gwifi)
......@@ -368,6 +383,114 @@ on_bss_removed (WPAInterface *object,
g_hash_table_remove (priv->ignored_bss_proxies, path);
}
static void
cancel_wifi_scan (GClueWifi *wifi)
{
GClueWifiPrivate *priv = wifi->priv;
if (priv->scan_timeout != 0) {
g_source_remove (priv->scan_timeout);
priv->scan_timeout = 0;
}
if (priv->scan_done_id != 0) {
g_signal_handler_disconnect (priv->interface,
priv->scan_done_id);
priv->scan_done_id = 0;
}
}
static gboolean
on_scan_timeout (gpointer user_data)
{
GClueWifi *wifi = GCLUE_WIFI (user_data);
GClueWifiPrivate *priv = wifi->priv;
GVariantBuilder builder;
GVariant *args;
if (priv->interface == NULL)
return FALSE;
g_debug ("WiFi scan timeout. Restarting-scan..");
priv->scan_timeout = 0;
if (priv->scan_done_id == 0)
priv->scan_done_id = g_signal_connect
(priv->interface,
"scan-done",
G_CALLBACK (on_scan_done),
wifi);
g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
g_variant_builder_add (&builder,
"{sv}",
"Type", g_variant_new ("s", "passive"));
args = g_variant_builder_end (&builder);
wpa_interface_call_scan (WPA_INTERFACE (priv->interface),
args,
NULL,
on_scan_call_done,
wifi);
return FALSE;
}
static void
on_scan_done (WPAInterface *object,
gboolean success,
gpointer user_data)
{
GClueWifi *wifi = GCLUE_WIFI (user_data);
GClueWifiPrivate *priv = wifi->priv;
if (!success) {
g_warning ("WiFi scan failed");
return;
}
g_debug ("WiFi scan completed");
if (priv->interface == NULL)
return;
gclue_web_source_refresh (GCLUE_WEB_SOURCE (wifi));
if (priv->accuracy_level >= GCLUE_ACCURACY_LEVEL_STREET)
/* With high-enough accuracy requests, we need to continuously
* keep scanning since user's location can change quickly. With
* low accuracy, we don't since we wouldn't want to drain power
* unnecessarily.
*/
on_scan_timeout (wifi);
else
priv->scan_timeout = g_timeout_add_seconds (WIFI_SCAN_TIMEOUT,
on_scan_timeout,
wifi);
}
static void
on_scan_call_done (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GClueWifi *wifi = GCLUE_WIFI (user_data);
GError *error = NULL;
if (!wpa_interface_call_scan_finish
(WPA_INTERFACE (source_object),
res,
&error)) {
g_warning ("Scanning of WiFi networks failed: %s",
error->message);
g_error_free (error);
cancel_wifi_scan (wifi);
return;
}
}
static void
connect_bss_signals (GClueWifi *wifi)
{
......@@ -383,6 +506,8 @@ connect_bss_signals (GClueWifi *wifi)
return;
}
on_scan_timeout (wifi);
priv->bss_added_id = g_signal_connect (priv->interface,
"bss-added",
G_CALLBACK (on_bss_added),
......@@ -411,6 +536,7 @@ disconnect_bss_signals (GClueWifi *wifi)
if (priv->bss_added_id == 0 || priv->interface == NULL)
return;
cancel_wifi_scan (wifi);
g_signal_handler_disconnect (priv->interface, priv->bss_added_id);
priv->bss_added_id = 0;
g_signal_handler_disconnect (priv->interface, priv->bss_removed_id);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment