mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-13 06:17:52 +08:00
💐 Sync 2026-10-06 12:33:44
This commit is contained in:
1 parent
8be03ce939
commit
7fe69dbb3a
246 files changed
+50330
-3414
No files matched your search
@@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
||||
LUCI_TITLE:=LuCI Status Pages
|
||||
LUCI_DEPENDS:=+luci-base +luci-app-oui +luci-mod-dashboard +libiwinfo +rpcd-mod-iwinfo +rpcd-mod-rrdns +ucode +ucode-mod-fs +ucode-mod-ubus +ucode-mod-socket
|
||||
|
||||
PKG_RELEASE:=30
|
||||
PKG_RELEASE:=31
|
||||
PKG_BUILD_DEPENDS:=iwinfo
|
||||
PKG_LICENSE:=Apache-2.0
|
||||
|
||||
|
||||
@@ -61,8 +61,10 @@ function getResolvedIwinfoDeviceName(net, deviceLookup) {
|
||||
const section = net.getName();
|
||||
const device = net.getWifiDeviceName();
|
||||
const fallback = getQcaFallbackIfname(device, section);
|
||||
const configuredIfname = uci.get('wireless', section, 'ifname');
|
||||
const isQca = isQcaWifiHwtype(uci.get('wireless', device, 'type'));
|
||||
|
||||
for (const candidate of [ ifname, section, fallback, device ])
|
||||
for (const candidate of [ configuredIfname, ifname, section, fallback, isQca ? null : device ])
|
||||
if (candidate && deviceLookup[candidate])
|
||||
return candidate;
|
||||
|
||||
@@ -86,6 +88,9 @@ function buildIwinfoResolver(radios, networks, devices) {
|
||||
}
|
||||
|
||||
networks.forEach((net) => {
|
||||
if (isNetworkDisabled(net))
|
||||
return;
|
||||
|
||||
const target = getResolvedIwinfoDeviceName(net, deviceLookup);
|
||||
const ifname = net.getIfname();
|
||||
const section = net.getName();
|
||||
@@ -104,6 +109,10 @@ function buildIwinfoResolver(radios, networks, devices) {
|
||||
|
||||
radios.forEach((radio) => {
|
||||
const name = radio.getName();
|
||||
if (uci.get('wireless', name, 'disabled') == '1' ||
|
||||
isQcaWifiHwtype(uci.get('wireless', name, 'type')))
|
||||
return;
|
||||
|
||||
const target = radioTargets[name] || (deviceLookup[name] ? name : null);
|
||||
|
||||
registerTarget(target);
|
||||
@@ -604,7 +613,21 @@ return baseclass.extend({
|
||||
}),
|
||||
|
||||
loadIwinfoResolver(radios, networks) {
|
||||
return L.resolveDefault(callIwinfoDevices(), []).then((devices) => {
|
||||
// Query enabled QCA VAPs only: probing a bare wifiN may create a
|
||||
// temporary VAP and block rpcd while the disabled radio starts up.
|
||||
const configuredRadios = uci.sections('wireless', 'wifi-device');
|
||||
const configOnly = configuredRadios.length > 0 &&
|
||||
configuredRadios.every((radio) => isQcaWifiHwtype(radio.type));
|
||||
const configuredDevices = [];
|
||||
|
||||
for (const iface of uci.sections('wireless', 'wifi-iface')) {
|
||||
if (iface.disabled == '1' || uci.get('wireless', iface.device, 'disabled') == '1')
|
||||
continue;
|
||||
|
||||
pushUnique(configuredDevices, iface.ifname || getQcaFallbackIfname(iface.device, iface['.name']));
|
||||
}
|
||||
|
||||
return (configOnly ? Promise.resolve(configuredDevices) : L.resolveDefault(callIwinfoDevices(), [])).then((devices) => {
|
||||
return buildIwinfoResolver(radios, networks, devices);
|
||||
}).catch(() => ({
|
||||
deviceLookup: Object.create(null),
|
||||
@@ -635,6 +658,9 @@ return baseclass.extend({
|
||||
},
|
||||
|
||||
getAssocListForNetwork(net) {
|
||||
if (isNetworkDisabled(net))
|
||||
return Promise.resolve([]);
|
||||
|
||||
const hwtype = uci.get('wireless', net.getWifiDeviceName(), 'type');
|
||||
const candidates = getAssocListCandidates(net, this.iwinfoResolver);
|
||||
const resolvedIfname = candidates[0];
|
||||
@@ -860,7 +886,8 @@ return baseclass.extend({
|
||||
}, this, radios_networks_hints[i])));
|
||||
}
|
||||
|
||||
if (hasWPS && uci.get('wireless', radios_networks_hints[i].sid, 'wps_pushbutton') == '1') {
|
||||
if (hasWPS && !isNetworkDisabled(radios_networks_hints[i]) &&
|
||||
uci.get('wireless', radios_networks_hints[i].sid, 'wps_pushbutton') == '1') {
|
||||
radios_networks_hints[i].isWPSEnabled = true;
|
||||
tasks.push(L.resolveDefault(this.handleGetWPSStatus(radios_networks_hints[i].getIfname()), null)
|
||||
.then(L.bind((net, data) => {
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
const assert = require('assert');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const source = fs.readFileSync(path.join(__dirname, '../htdocs/luci-static/resources/view/status/include/60_wifi.js'), 'utf8');
|
||||
let config, calls, enumerated;
|
||||
const uci = {
|
||||
get: (pkg, section, key) => config[section]?.[key],
|
||||
sections: (pkg, type) => Object.entries(config).filter(([, s]) => s['.type'] == type).map(([name, s]) => ({'.name': name, ...s}))
|
||||
};
|
||||
const view = new Function('baseclass', 'rpc', 'uci', 'L', '_', source)(
|
||||
{extend: o => o},
|
||||
{declare: spec => async (...args) => {
|
||||
calls.push([spec.method, ...args]);
|
||||
return spec.method == 'devices' ? enumerated : [];
|
||||
}}, uci,
|
||||
{toArray: x => x || [], resolveDefault: (p, fallback) => p.catch(() => fallback)}, s => s
|
||||
);
|
||||
function setup() {
|
||||
config = {
|
||||
wifi0: {'.type':'wifi-device', type:'qcawificfg80211', disabled:'1'},
|
||||
wifi1: {'.type':'wifi-device', type:'qcawifi', disabled:'1'},
|
||||
ath0: {'.type':'wifi-iface', device:'wifi0'},
|
||||
ath1: {'.type':'wifi-iface', device:'wifi1'}
|
||||
};
|
||||
calls = [];
|
||||
enumerated = ['wifi0', 'wifi1'];
|
||||
}
|
||||
function radios() { return uci.sections('wireless', 'wifi-device').map(s => ({getName: () => s['.name']})); }
|
||||
function networks() { return uci.sections('wireless', 'wifi-iface').map(s => ({
|
||||
getName: () => s['.name'], getWifiDeviceName: () => s.device,
|
||||
getIfname: () => s.device + '.network1', get: key => s[key],
|
||||
getAssocList: async () => {calls.push(['net-assoc', s['.name']]); return [];}
|
||||
})); }
|
||||
(async () => {
|
||||
setup();
|
||||
let resolver = await view.loadIwinfoResolver(radios(), networks());
|
||||
assert.deepEqual(resolver.queryTargets, []);
|
||||
await view.loadIwinfoInfoMap(resolver);
|
||||
for (const net of networks()) assert.deepEqual(await view.getAssocListForNetwork(net), []);
|
||||
assert.deepEqual(calls, [], 'disabled radios must issue no iwinfo or association queries');
|
||||
config.wifi0.disabled = '0';
|
||||
resolver = await view.loadIwinfoResolver(radios(), networks());
|
||||
assert.deepEqual(resolver.queryTargets, ['ath0']);
|
||||
assert.equal(resolver.aliasMap.wifi0, 'ath0');
|
||||
config.ath0.disabled = '1';
|
||||
resolver = await view.loadIwinfoResolver(radios(), networks());
|
||||
assert.deepEqual(resolver.queryTargets, [], 'disabled VAP is excluded even on an enabled radio');
|
||||
config.ath0.disabled = '0';
|
||||
config.ath0.ifname = 'custom0';
|
||||
resolver = await view.loadIwinfoResolver(radios(), networks());
|
||||
assert.deepEqual(resolver.queryTargets, ['custom0']);
|
||||
delete config.ath0;
|
||||
resolver = await view.loadIwinfoResolver(radios(), networks());
|
||||
assert.deepEqual(resolver.queryTargets, [], 'no VAP must not fall back to the bare QCA radio');
|
||||
setup();
|
||||
config.radio0 = {'.type':'wifi-device', type:'mac80211'};
|
||||
enumerated.push('radio0');
|
||||
resolver = await view.loadIwinfoResolver(radios(), networks());
|
||||
assert.deepEqual(resolver.queryTargets, ['radio0']);
|
||||
assert.deepEqual(calls, [['devices']], 'mixed setups retain generic enumeration');
|
||||
config.wifi0.disabled = '0';
|
||||
resolver = await view.loadIwinfoResolver(radios(), networks());
|
||||
assert.deepEqual(resolver.queryTargets, ['radio0'], 'mixed setups must not probe bare QCA radios');
|
||||
console.log('Wi-Fi status: disabled radios/VAPs, active VAP, custom ifname, missing VAP and mixed backends passed');
|
||||
})().catch(e => {console.error(e); process.exit(1);});
|
||||
Reference in new issue
Block a user