mirror of
https://github.com/koreader/koreader.git
synced 2025-08-10 00:52:38 +00:00
NetworkManager: Always prefer system APs as intended.
If we had a local prefered AP with a higher RSSI, we attempted to associate with it over wpa_supplicant being already attempting to associate with its own preferred AP. That... failed horribly. Also adapt to the new lj-wpaclient API, fixing a few other edge-cases, and making the whole thing slightly faster because we no longer uselessly sleep. And more reliable because we now actually wait for replies to our requests. Bump base https://github.com/koreader/koreader-base/pull/1424
This commit is contained in:
2
base
2
base
Submodule base updated: 5c8fa477f8...e0643c89f9
@@ -599,6 +599,7 @@ function NetworkMgr:reconnectOrShowNetworkMenu(complete_callback)
|
||||
-- rescan if the first scan appeared to yield an empty list.
|
||||
--- @fixme This *might* be an issue better handled in lj-wpaclient...
|
||||
if #network_list == 0 then
|
||||
logger.warn("Initial Wi-Fi scan yielded no results, rescanning")
|
||||
network_list, err = self:getNetworkList()
|
||||
if network_list == nil then
|
||||
UIManager:show(InfoMessage:new{text = err})
|
||||
@@ -613,27 +614,53 @@ function NetworkMgr:reconnectOrShowNetworkMenu(complete_callback)
|
||||
if self.wifi_toggle_long_press then
|
||||
self.wifi_toggle_long_press = nil
|
||||
else
|
||||
local ssid
|
||||
-- We need to do two passes, as we may have *both* an already connected network (from the global wpa config),
|
||||
-- *and* preferred networks, and if the prferred networks have a better signal quality,
|
||||
-- they'll be sorted *earlier*, which would cause us to try to associate to a different AP than
|
||||
-- what wpa_supplicant is already trying to do...
|
||||
for dummy, network in ipairs(network_list) do
|
||||
if network.connected then
|
||||
-- On platforms where we use wpa_supplicant (if we're calling this, we are),
|
||||
-- the invocation will check its global config, and if an AP configured there is reachable,
|
||||
-- it'll already have connected to it on its own.
|
||||
success = true
|
||||
elseif network.password then
|
||||
success = NetworkMgr:authenticateNetwork(network)
|
||||
end
|
||||
if success then
|
||||
NetworkMgr:obtainIP()
|
||||
if complete_callback then
|
||||
complete_callback()
|
||||
end
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = T(_("Connected to network %1"), BD.wrap(network.ssid)),
|
||||
timeout = 3,
|
||||
})
|
||||
ssid = network.ssid
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
-- Next, look for our own prferred networks...
|
||||
local err_msg = _("Connection failed")
|
||||
if not success then
|
||||
for dummy, network in ipairs(network_list) do
|
||||
if network.password then
|
||||
-- If we hit a preferred network and we're not already connected,
|
||||
-- attempt to connect to said preferred network....
|
||||
success, err_msg = NetworkMgr:authenticateNetwork(network)
|
||||
if success then
|
||||
ssid = network.ssid
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if success then
|
||||
NetworkMgr:obtainIP()
|
||||
if complete_callback then
|
||||
complete_callback()
|
||||
end
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = T(_("Connected to network %1"), BD.wrap(ssid)),
|
||||
timeout = 3,
|
||||
})
|
||||
else
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = err_msg,
|
||||
timeout = 3,
|
||||
})
|
||||
end
|
||||
end
|
||||
if not success then
|
||||
-- NOTE: Also supports a disconnect_callback, should we use it for something?
|
||||
|
||||
@@ -4,7 +4,7 @@ WPA client helper for Kobo.
|
||||
|
||||
local FFIUtil = require("ffi/util")
|
||||
local InfoMessage = require("ui/widget/infomessage")
|
||||
local WpaClient = require('lj-wpaclient/wpaclient')
|
||||
local WpaClient = require("lj-wpaclient/wpaclient")
|
||||
local UIManager = require("ui/uimanager")
|
||||
local _ = require("gettext")
|
||||
local T = FFIUtil.template
|
||||
@@ -20,13 +20,17 @@ function WpaSupplicant:getNetworkList()
|
||||
return nil, T(CLIENT_INIT_ERR_MSG, err)
|
||||
end
|
||||
|
||||
local list = wcli:scanThenGetResults()
|
||||
local list
|
||||
list, err = wcli:scanThenGetResults()
|
||||
wcli:close()
|
||||
if list == nil then
|
||||
return nil, T("An error occurred while scanning: %1.", err)
|
||||
end
|
||||
|
||||
local saved_networks = self:getAllSavedNetworks()
|
||||
local curr_network = self:getCurrentNetwork()
|
||||
|
||||
for _,network in ipairs(list) do
|
||||
for _, network in ipairs(list) do
|
||||
network.signal_quality = network:getSignalQuality()
|
||||
local saved_nw = saved_networks:readSetting(network.ssid)
|
||||
if saved_nw then
|
||||
@@ -58,27 +62,30 @@ end
|
||||
|
||||
--- Authenticates network.
|
||||
function WpaSupplicant:authenticateNetwork(network)
|
||||
local err, wcli, nw_id
|
||||
local wcli, reply, err
|
||||
|
||||
wcli, err = WpaClient.new(self.wpa_supplicant.ctrl_interface)
|
||||
if not wcli then
|
||||
return false, T(CLIENT_INIT_ERR_MSG, err)
|
||||
end
|
||||
|
||||
nw_id, err = wcli:addNetwork()
|
||||
if err then return false, err end
|
||||
reply, err = wcli:addNetwork()
|
||||
if reply == nil then
|
||||
return false, err
|
||||
end
|
||||
local nw_id = reply
|
||||
|
||||
local re = wcli:setNetwork(nw_id, "ssid", string.format("\"%s\"", network.ssid))
|
||||
if re == "FAIL" then
|
||||
reply, err = wcli:setNetwork(nw_id, "ssid", string.format("\"%s\"", network.ssid))
|
||||
if reply == nil or reply == "FAIL" then
|
||||
wcli:removeNetwork(nw_id)
|
||||
return false, _("An error occurred while selecting network.")
|
||||
return false, T("An error occurred while selecting network: %1.", err)
|
||||
end
|
||||
-- if password is empty it’s an open AP
|
||||
if network.password and #network.password == 0 then -- Open AP
|
||||
re = wcli:setNetwork(nw_id, "key_mgmt", "NONE")
|
||||
if re == "FAIL" then
|
||||
reply, err = wcli:setNetwork(nw_id, "key_mgmt", "NONE")
|
||||
if reply == nil or reply == "FAIL" then
|
||||
wcli:removeNetwork(nw_id)
|
||||
return false, _("An error occurred while setting passwordless mode.")
|
||||
return false, T("An error occurred while setting passwordless mode: %1.", err)
|
||||
end
|
||||
-- else it’s a WPA AP
|
||||
else
|
||||
@@ -86,10 +93,10 @@ function WpaSupplicant:authenticateNetwork(network)
|
||||
network.psk = calculatePsk(network.ssid, network.password)
|
||||
self:saveNetwork(network)
|
||||
end
|
||||
re = wcli:setNetwork(nw_id, "psk", network.psk)
|
||||
if re == "FAIL" then
|
||||
reply, err = wcli:setNetwork(nw_id, "psk", network.psk)
|
||||
if reply == nil or reply == "FAIL" then
|
||||
wcli:removeNetwork(nw_id)
|
||||
return false, _("An error occurred while setting password.")
|
||||
return false, T("An error occurred while setting password: %1.", err)
|
||||
end
|
||||
end
|
||||
wcli:enableNetworkByID(nw_id)
|
||||
@@ -99,10 +106,32 @@ function WpaSupplicant:authenticateNetwork(network)
|
||||
local failure_cnt = 0
|
||||
local max_retry = 30
|
||||
local info = InfoMessage:new{text = _("Authenticating…")}
|
||||
local msg
|
||||
local success = false
|
||||
local msg = _("Authenticated")
|
||||
UIManager:show(info)
|
||||
UIManager:forceRePaint()
|
||||
while cnt < max_retry do
|
||||
-- Start by checking if we're not actually connected already...
|
||||
-- NOTE: This is mainly to catch corner-cases where our preferred network list differs from the system's,
|
||||
-- and ours happened to be sorted earlier because of a better signal quality...
|
||||
local connected, state = wcli:getConnectedNetwork()
|
||||
if connected then
|
||||
network.wpa_supplicant_id = connected.id
|
||||
network.ssid = connected.ssid
|
||||
success = true
|
||||
break
|
||||
else
|
||||
if state then
|
||||
UIManager:close(info)
|
||||
-- Make the state prettier
|
||||
local first, rest = state:sub(1, 1), state:sub(2)
|
||||
info = InfoMessage:new{text = string.upper(first) .. string.lower(rest) .. "…"}
|
||||
UIManager:show(info)
|
||||
UIManager:forceRePaint()
|
||||
end
|
||||
end
|
||||
|
||||
-- Otherwise, poke at the wpa_supplicant socket for a bit...
|
||||
local ev = wcli:readEvent()
|
||||
if ev ~= nil then
|
||||
if not ev:isScanEvent() then
|
||||
@@ -113,28 +142,30 @@ function WpaSupplicant:authenticateNetwork(network)
|
||||
end
|
||||
if ev:isAuthSuccessful() then
|
||||
network.wpa_supplicant_id = nw_id
|
||||
re = true
|
||||
success = true
|
||||
break
|
||||
elseif ev:isAuthFailed() then
|
||||
failure_cnt = failure_cnt + 1
|
||||
if failure_cnt > 3 then
|
||||
re, msg = false, _("Failed to authenticate")
|
||||
success, msg = false, _("Failed to authenticate")
|
||||
break
|
||||
end
|
||||
end
|
||||
else
|
||||
FFIUtil.sleep(1)
|
||||
wcli:waitForEvent(1 * 1000)
|
||||
cnt = cnt + 1
|
||||
end
|
||||
end
|
||||
if re ~= true then wcli:removeNetwork(nw_id) end
|
||||
if success ~= true then
|
||||
wcli:removeNetwork(nw_id)
|
||||
end
|
||||
wcli:close()
|
||||
UIManager:close(info)
|
||||
UIManager:forceRePaint()
|
||||
if cnt >= max_retry then
|
||||
re, msg = false, _("Timed out")
|
||||
success, msg = false, _("Timed out")
|
||||
end
|
||||
return re, msg
|
||||
return success, msg
|
||||
end
|
||||
|
||||
function WpaSupplicant:disconnectNetwork(network)
|
||||
|
||||
Reference in New Issue
Block a user