NetworkMgr: Attempt to handle wpa_supplicant rescans better (#12236)

Namely, in the face of wpa_supplicant doing multiple scans. Note that a backend PR will make this largely redundant, by actually fixing the core issue in our backend ;).

Also add more logging around the authentication status.
This commit is contained in:
NiLuJe
2024-07-30 11:44:45 +02:00
committed by GitHub
parent 45d1a14aed
commit 5c77774ca9
2 changed files with 69 additions and 5 deletions

View File

@@ -176,6 +176,7 @@ function NetworkMgr:isConnected()
end
end
function NetworkMgr:getNetworkInterfaceName() end
function NetworkMgr:getConfiguredNetworks() end -- From the *backend*, e.g., wpa_cli list_networks (as opposed to `getAllSavedNetworks`)
function NetworkMgr:getNetworkList() end
function NetworkMgr:getCurrentNetwork() end
function NetworkMgr:authenticateNetwork(network) end
@@ -1105,16 +1106,50 @@ function NetworkMgr:reconnectOrShowNetworkMenu(complete_callback, interactive)
if network.password then
-- If we hit a preferred network and we're not already connected,
-- attempt to connect to said preferred network....
logger.dbg("NetworkMgr: Attempting to authenticate on preferred network", util.fixUtf8(ssid, "<EFBFBD>"))
success, err_msg = self:authenticateNetwork(network)
if success then
ssid = network.ssid
network.connected = true
break
else
logger.dbg("NetworkMgr: authentication failed:", err_msg)
end
end
end
end
-- If we haven't even seen any of our preferred networks, wait a bit to see if wpa_supplicant manages to connect in the background anyway...
-- This happens when we break too early from re-scans triggered by wpa_supplicant itself,
-- which shouldn't really ever happen since https://github.com/koreader/lj-wpaclient/pull/11
-- c.f., WpaClient:scanThenGetResults in lj-wpaclient for more details.
if Device:hasWifiManager() and not success and not ssid then
-- Don't bother if wpa_supplicant doesn't actually have any configured networks...
local configured_networks = self:getConfiguredNetworks()
local has_preferred_networks = configured_networks and #configured_networks > 0
local iter = has_preferred_networks and 0 or 60
-- We wait 15s at most (like the restore-wifi-async script)
while not success and iter < 60 do
-- Check every 250ms
iter = iter + 1
ffiutil.usleep(250 * 1e+3)
local nw = self:getCurrentNetwork()
if nw then
success = true
ssid = nw.ssid
-- Flag it as connected in the list
for dummy, network in ipairs(network_list) do
if ssid == network.ssid then
network.connected = true
end
end
logger.dbg("NetworkMgr: wpa_supplicant automatically connected to network", util.fixUtf8(ssid, "<EFBFBD>"), "(after", iter * 0.25, "seconds)")
end
end
end
if success then
self:obtainIP()
if complete_callback then
@@ -1129,11 +1164,13 @@ function NetworkMgr:reconnectOrShowNetworkMenu(complete_callback, interactive)
text = T(_(Device:isKindle() and "Connecting to network %1…" or "Connected to network %1"), BD.wrap(util.fixUtf8(ssid, "<EFBFBD>"))),
timeout = 3,
})
logger.dbg("NetworkMgr: Connected to network", util.fixUtf8(ssid, "<EFBFBD>"))
else
UIManager:show(InfoMessage:new{
text = err_msg,
timeout = 3,
})
logger.dbg("NetworkMgr: Failed to connect:", err_msg, "; last attempt on ssid:", ssid and util.fixUtf8(ssid, "<EFBFBD>") or "<none>")
end
if not success then

View File

@@ -8,6 +8,8 @@ local FFIUtil = require("ffi/util")
local InfoMessage = require("ui/widget/infomessage")
local WpaClient = require("lj-wpaclient/wpaclient")
local UIManager = require("ui/uimanager")
local logger = require("logger")
local util = require("util")
local _ = require("gettext")
local T = FFIUtil.template
@@ -54,15 +56,17 @@ function WpaSupplicant:getNetworkList()
network.signal_quality = network:getSignalQuality()
local saved_nw = saved_networks:readSetting(network.ssid)
if saved_nw then
--- @todo verify saved_nw.flags == network.flags? This will break if user changed the
-- network setting from [WPA-PSK-TKIP+CCMP][WPS][ESS] to [WPA-PSK-TKIP+CCMP][ESS]
--- @todo verify saved_nw.flags == network.flags?
-- This will break if user changed the network setting, e.g.,
-- from [WPA-PSK-TKIP+CCMP][WPS][ESS]
-- to [WPA-PSK-TKIP+CCMP][ESS]
network.password = saved_nw.password
network.psk = saved_nw.psk
end
--- @todo also verify bssid if it is not set to any
if curr_network and curr_network.ssid == network.ssid then
if curr_network and curr_network.ssid == network.ssid and (curr_network.bssid == "any" or curr_network.bssid == network.bssid) then
network.connected = true
network.wpa_supplicant_id = curr_network.id
logger.dbg("WpaSupplicant:getNetworkList: automatically connected to network", util.fixUtf8(curr_network.ssid, "<EFBFBD>"))
end
end
return list
@@ -195,7 +199,16 @@ function WpaSupplicant:getCurrentNetwork()
if wcli == nil then
return nil, T(CLIENT_INIT_ERR_MSG, err)
end
local nw = wcli:getCurrentNetwork()
-- Start by checking the status before looking for the CURRENT flag...
local nw
nw, err = wcli:getConnectedNetwork()
logger.dbg("WpaSupplicant:getCurrentNetwork: Connected network:", nw and nw or err)
-- Then fall back to the flag check...
if nw == nil then
nw, err = wcli:getCurrentNetwork()
logger.dbg("WpaSupplicant:getCurrentNetwork: Current network:", nw and nw or err)
end
wcli:close()
if nw ~= nil then
nw.ssid = decodeSSID(nw.ssid)
@@ -203,8 +216,22 @@ function WpaSupplicant:getCurrentNetwork()
return nw
end
function WpaSupplicant:getConfiguredNetworks()
local wcli, err = WpaClient.new(self.wpa_supplicant.ctrl_interface)
if wcli == nil then
return nil, T(CLIENT_INIT_ERR_MSG, err)
end
local nw
nw, err = wcli:listNetworks()
wcli:close()
return nw, err
end
function WpaSupplicant.init(network_mgr, options)
network_mgr.wpa_supplicant = {ctrl_interface = options.ctrl_interface}
network_mgr.getConfiguredNetworks = WpaSupplicant.getConfiguredNetworks
network_mgr.getNetworkList = WpaSupplicant.getNetworkList
network_mgr.getCurrentNetwork = WpaSupplicant.getCurrentNetwork
network_mgr.authenticateNetwork = WpaSupplicant.authenticateNetwork