diff --git a/frontend/ui/network/manager.lua b/frontend/ui/network/manager.lua index 8559215fb..a9de9b6c7 100644 --- a/frontend/ui/network/manager.lua +++ b/frontend/ui/network/manager.lua @@ -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, "�")) 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, "�"), "(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, "�"))), timeout = 3, }) + logger.dbg("NetworkMgr: Connected to network", util.fixUtf8(ssid, "�")) 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, "�") or "") end if not success then diff --git a/frontend/ui/network/wpa_supplicant.lua b/frontend/ui/network/wpa_supplicant.lua index 5bf2f177c..8f73be110 100644 --- a/frontend/ui/network/wpa_supplicant.lua +++ b/frontend/ui/network/wpa_supplicant.lua @@ -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, "�")) 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