luci: optimization

This commit is contained in:
xiaorouji 2024-01-29 01:36:47 +08:00 committed by sbwml
parent 637373e639
commit 463d899505
13 changed files with 171 additions and 172 deletions

View File

@ -246,16 +246,15 @@ function ping_node()
local index = luci.http.formvalue("index")
local address = luci.http.formvalue("address")
local port = luci.http.formvalue("port")
local type = luci.http.formvalue("type") or "icmp"
local e = {}
e.index = index
local nodes_ping = ucic:get(appname, "@global_other[0]", "nodes_ping") or ""
if nodes_ping:find("tcping") and luci.sys.exec("echo -n $(command -v tcping)") ~= "" then
if type == "tcping" and luci.sys.exec("echo -n $(command -v tcping)") ~= "" then
if api.is_ipv6(address) then
address = api.get_ipv6_only(address)
end
e.ping = luci.sys.exec(string.format("echo -n $(tcping -q -c 1 -i 1 -t 2 -p %s %s 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null", port, address))
end
if e.ping == nil or tonumber(e.ping) == 0 then
else
e.ping = luci.sys.exec("echo -n $(ping -c 1 -W 1 %q 2>&1 | grep -o 'time=[0-9]*' | awk -F '=' '{print $2}') 2>/dev/null" % address)
end
luci.http.prepare_content("application/json")

View File

@ -5,6 +5,10 @@ local has_singbox = api.finded_com("singbox")
local has_xray = api.finded_com("xray")
local has_chnlist = api.fs.access("/usr/share/passwall/rules/chnlist")
local port_validate = function(self, value, t)
return value:gsub("-", ":")
end
m = Map(appname)
local nodes_table = {}
@ -141,6 +145,7 @@ o.default = "default"
o:value("disable", translate("No patterns are used"))
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
o.validate = port_validate
---- UDP No Redir Ports
o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"))
@ -148,12 +153,14 @@ o.default = "default"
o:value("disable", translate("No patterns are used"))
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
o.validate = port_validate
---- TCP Proxy Drop Ports
o = s:option(Value, "tcp_proxy_drop_ports", translate("TCP Proxy Drop Ports"))
o.default = "default"
o:value("disable", translate("No patterns are used"))
o:value("default", translate("Default"))
o.validate = port_validate
---- UDP Proxy Drop Ports
o = s:option(Value, "udp_proxy_drop_ports", translate("UDP Proxy Drop Ports"))
@ -161,6 +168,7 @@ o.default = "default"
o:value("disable", translate("No patterns are used"))
o:value("default", translate("Default"))
o:value("80,443", translate("QUIC"))
o.validate = port_validate
---- TCP Redir Ports
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
@ -170,6 +178,7 @@ o:value("1:65535", translate("All"))
o:value("80,443", "80,443")
o:value("80:65535", "80 " .. translate("or more"))
o:value("1:443", "443 " .. translate("or less"))
o.validate = port_validate
---- UDP Redir Ports
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
@ -177,6 +186,7 @@ o.default = "default"
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
o:value("53", "53")
o.validate = port_validate
---- TCP Proxy Mode
tcp_proxy_mode = s:option(ListValue, "tcp_proxy_mode", "TCP " .. translate("Proxy Mode"))

View File

@ -49,7 +49,7 @@ o:depends("balancing_enable", true)
o = s:option(ListValue, "health_check_type", translate("Health Check Type"))
o.default = "passwall_logic"
o:value("tcp", "TCP")
o:value("passwall_logic", translate("Availability test") .. string.format("(passwall %s)", translate("Inner implement")))
o:value("passwall_logic", translate("URL Test") .. string.format("(passwall %s)", translate("Inner implement")))
o:depends("balancing_enable", true)
---- Health Check Inter
@ -60,7 +60,7 @@ o:depends("balancing_enable", true)
o = s:option(DummyValue, "health_check_tips", " ")
o.rawhtml = true
o.cfgvalue = function(t, n)
return string.format('<span style="color: red">%s</span>', translate("When the availability test is used, the load balancing node will be converted into a Socks node. when node list set customizing, must be a Socks node, otherwise the health check will be invalid."))
return string.format('<span style="color: red">%s</span>', translate("When the URL test is used, the load balancing node will be converted into a Socks node. when node list set customizing, must be a Socks node, otherwise the health check will be invalid."))
end
o:depends("health_check_type", "passwall_logic")

View File

@ -9,15 +9,19 @@ m = Map(appname)
s = m:section(TypedSection, "global_other")
s.anonymous = true
o = s:option(MultiValue, "nodes_ping", " ")
o:value("auto_ping", translate("Auto Ping"), translate("This will automatically ping the node for latency"))
o:value("tcping", translate("Tcping"), translate("This will use tcping replace ping detection of node"))
o:value("info", translate("Show server address and port"), translate("Show server address and port"))
o = s:option(ListValue, "auto_detection_time", translate("Automatic detection delay"))
o:value("0", translate("Close"))
o:value("icmp", "Ping")
o:value("tcping", "TCP Ping")
o = s:option(Flag, "show_node_info", translate("Show server address and port"))
o.default = "0"
-- [[ Add the node via the link ]]--
s:append(Template(appname .. "/node_list/link_add_node"))
local nodes_ping = m:get("@global_other[0]", "nodes_ping") or ""
local auto_detection_time = m:get("@global_other[0]", "auto_detection_time") or "0"
local show_node_info = m:get("@global_other[0]", "show_node_info") or "0"
-- [[ Node List ]]--
s = m:section(TypedSection, "nodes")
@ -113,7 +117,7 @@ o.cfgvalue = function(t, n)
local port = m:get(n, "port") or ""
str = str .. translate(type) .. "" .. remarks
if address ~= "" and port ~= "" then
if nodes_ping:find("info") then
if show_node_info == "1" then
if datatypes.ip6addr(address) then
str = str .. string.format("[%s]:%s", address, port)
else
@ -127,23 +131,38 @@ o.cfgvalue = function(t, n)
end
---- Ping
o = s:option(DummyValue, "ping")
o = s:option(DummyValue, "ping", "Ping")
o.width = "8%"
o.rawhtml = true
o.cfgvalue = function(t, n)
local result = "---"
if not nodes_ping:find("auto_ping") then
result = string.format('<span class="ping"><a href="javascript:void(0)" onclick="javascript:ping_node(\'%s\',this)">Ping</a></span>', n)
if auto_detection_time ~= "icmp" then
result = string.format('<span class="ping"><a href="javascript:void(0)" onclick="javascript:ping_node(\'%s\', this, \'icmp\')">%s</a></span>', n, translate("Test"))
else
result = string.format('<span class="ping_value" cbiid="%s">---</span>', n)
end
return result
end
o = s:option(DummyValue, "_url_test")
---- TCP Ping
o = s:option(DummyValue, "tcping", "TCPing")
o.width = "8%"
o.rawhtml = true
o.cfgvalue = function(t, n)
return string.format('<input type="button" class="cbi-button" value="%s" onclick="javascript:urltest_node(\'%s\',this)"', translate("Availability test"), n)
local result = "---"
if auto_detection_time ~= "tcping" then
result = string.format('<span class="ping"><a href="javascript:void(0)" onclick="javascript:ping_node(\'%s\', this, \'tcping\')">%s</a></span>', n, translate("Test"))
else
result = string.format('<span class="tcping_value" cbiid="%s">---</span>', n)
end
return result
end
o = s:option(DummyValue, "_url_test", translate("URL Test"))
o.width = "8%"
o.rawhtml = true
o.cfgvalue = function(t, n)
return string.format('<span class="ping"><a href="javascript:void(0)" onclick="javascript:urltest_node(\'%s\', this)">%s</a></span>', n, translate("Test"))
end
m:append(Template(appname .. "/node_list/node_list"))

View File

@ -6,6 +6,10 @@ local has_xray = api.finded_com("xray")
local has_fw3 = api.is_finded("fw3")
local has_fw4 = api.is_finded("fw4")
local port_validate = function(self, value, t)
return value:gsub("-", ":")
end
m = Map(appname)
-- [[ Delay Settings ]]--
@ -63,6 +67,7 @@ o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports"))
o.default = "disable"
o:value("disable", translate("No patterns are used"))
o:value("1:65535", translate("All"))
o.validate = port_validate
---- UDP No Redir Ports
o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"),
@ -72,17 +77,20 @@ o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"),
o.default = "disable"
o:value("disable", translate("No patterns are used"))
o:value("1:65535", translate("All"))
o.validate = port_validate
---- TCP Proxy Drop Ports
o = s:option(Value, "tcp_proxy_drop_ports", translate("TCP Proxy Drop Ports"))
o.default = "disable"
o:value("disable", translate("No patterns are used"))
o.validate = port_validate
---- UDP Proxy Drop Ports
o = s:option(Value, "udp_proxy_drop_ports", translate("UDP Proxy Drop Ports"))
o.default = "443"
o:value("disable", translate("No patterns are used"))
o:value("443", translate("QUIC"))
o.validate = port_validate
---- TCP Redir Ports
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
@ -90,12 +98,14 @@ o.default = "22,25,53,143,465,587,853,993,995,80,443"
o:value("1:65535", translate("All"))
o:value("22,25,53,143,465,587,853,993,995,80,443", translate("Common Use"))
o:value("80,443", translate("Only Web"))
o.validate = port_validate
---- UDP Redir Ports
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
o.default = "1:65535"
o:value("1:65535", translate("All"))
o:value("53", "DNS")
o.validate = port_validate
---- Use nftables
o = s:option(ListValue, "use_nft", translate("Firewall tools"))

View File

@ -41,7 +41,7 @@ o:value("trojan", translate("Trojan"))
o:value("wireguard", translate("WireGuard"))
o:value("_balancing", translate("Balancing"))
o:value("_shunt", translate("Shunt"))
o:value("_iface", translate("Custom Interface") .. " (Only Support Xray)")
o:value("_iface", translate("Custom Interface"))
o = s:option(Value, option_name("iface"), translate("Interface"))
o.default = "eth1"

View File

@ -58,7 +58,7 @@ if singbox_tags:find("with_quic") then
o:value("hysteria2", "Hysteria2")
end
o:value("_shunt", translate("Shunt"))
o:value("_iface", translate("Custom Interface") .. " (Only Support Xray)")
o:value("_iface", translate("Custom Interface"))
o = s:option(Value, option_name("iface"), translate("Interface"))
o.default = "eth1"

View File

@ -345,7 +345,7 @@ o = s:option(ListValue, option_name("outbound_node"), translate("outbound node")
o:value("nil", translate("Close"))
o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP"))
o:value("_iface", translate("Custom Interface") .. " (Only Support Xray)")
o:value("_iface", translate("Custom Interface"))
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
o.default = "nil"

View File

@ -307,7 +307,7 @@ function get_domain_from_url(url)
end
function get_valid_nodes()
local nodes_ping = uci_get_type("global_other", "nodes_ping") or ""
local show_node_info = uci_get_type("global_other", "show_node_info") or "0"
local nodes = {}
uci:foreach(appname, "nodes", function(e)
e.id = e[".name"]
@ -334,7 +334,7 @@ function get_valid_nodes()
end
if is_ipv6(address) then address = get_ipv6_full(address) end
e["remark"] = "%s[%s]" % {type, e.remarks}
if nodes_ping:find("info") then
if show_node_info == "1" then
e["remark"] = "%s[%s] %s:%s" % {type, e.remarks, address, e.port}
end
e.node_type = "normal"

View File

@ -48,9 +48,8 @@ local api = require "luci.passwall.api"
function add_node() {
var nodes_link = document.getElementById("nodes_link").value;
if (nodes_link.trim() != "") {
var supports = "ss ssr vmess vless trojan trojan-go hysteria";
var itype = nodes_link.split('://')[0];
if (itype.trim() != "" && supports.indexOf(itype) >= 0) {
var s = nodes_link.split('://');
if (s.length > 1) {
ajax_add_node(nodes_link);
}
else {
@ -81,9 +80,10 @@ local api = require "luci.passwall.api"
<div id="add_link_div">
<div class="cbi-value">
<label class="cbi-value-title"><%:SS/SSR/Vmess/VLESS/Trojan/Hysteria Link%></label>
<label class="cbi-value-title"><%:Share Link%></label>
<div class="cbi-value-field">
<textarea id="nodes_link" rows="5" cols="50"></textarea>
<p><textarea id="nodes_link" rows="5" cols="50"></textarea></p>
<font color="red"><%:Not a subscription link!!!%></font>
</div>
</div>
<div class="cbi-value">
@ -103,6 +103,8 @@ local api = require "luci.passwall.api"
<input class="btn cbi-button cbi-button-remove" type="button" onclick="delete_select_nodes()" value="<%:Delete select nodes%>" />
<input class="btn cbi-button" type="button" onclick="checked_all_node(this)" value="<%:Select all%>" />
<input class="btn cbi-button cbi-button-apply" type="submit" name="cbi.apply" value="<%:Save & Apply%>" />
<input class="btn cbi-button cbi-button-save" type="submit" name="cbi.save" value="<%:Save%>" />
<input class="btn cbi-button cbi-button-reset" type="button" value="<%:Reset%>" onclick="location.href='<%=REQUEST_URI%>'" />
<div id="div_node_count"></div>
</div>
</div>

View File

@ -36,6 +36,8 @@ table td, .table .td {
<script type="text/javascript">
//<![CDATA[
let auto_detection_time = "<%=api.uci_get_type("global_other", "auto_detection_time", "0")%>"
var node_list = {};
var node_count = 0;
@ -229,8 +231,8 @@ table td, .table .td {
function urltest_node(cbi_id, dom) {
if (cbi_id != null) {
dom.disabled = true;
dom.value = "<%:Check...%>";
dom.onclick = null
dom.innerText = "<%:Check...%>";
XHR.get('<%=api.url("urltest_node")%>', {
id: cbi_id
},
@ -241,6 +243,7 @@ table td, .table .td {
} else {
var color = "red";
var use_time = result.use_time;
use_time = parseInt(use_time) + 1;
if (use_time < 1000) {
color = "green";
} else if (use_time < 2000) {
@ -248,20 +251,25 @@ table td, .table .td {
} else {
color = "red";
}
dom.outerHTML = "<font style='color:" + color + "'>" + result.use_time + " ms" + "</font>";
dom.outerHTML = "<font style='color:" + color + "'>" + use_time + " ms" + "</font>";
}
} else {
dom.outerHTML = "<font style='color:red'><%:Error%></font>";
}
}
);
}
}
function ping_node(cbi_id, dom) {
function ping_node(cbi_id, dom, type) {
var full = get_address_full(cbi_id);
if (full != null) {
dom.onclick = null
dom.innerText = "<%:Check...%>";
XHR.get('<%=api.url("ping_node")%>', {
address: full.address,
port: full.port
port: full.port,
type: type
},
function(x, result) {
if(x && x.status == 200) {
@ -282,131 +290,87 @@ table td, .table .td {
}
}
/* 自动Ping */
var nodes = [];
const ping_value = document.getElementsByClassName('ping_value');
for (var i = 0; i < ping_value.length; i++) {
var cbi_id = ping_value[i].getAttribute("cbiid");
var full = get_address_full(cbi_id);
if (full != null) {
var flag = false;
//当有多个相同地址和端口时合在一起
for (var j = 0; j < nodes.length; j++) {
if (nodes[j].address == full.address && nodes[j].port == full.port) {
nodes[j].indexs = nodes[j].indexs + "," + i;
flag = true;
break;
}
}
if (flag)
continue;
nodes.push({
indexs: i + "",
address: full.address,
port: full.port
});
}
}
get_now_use_node();
const _xhr = (index) => {
return new Promise((res) => {
const dom = nodes[index];
if (!dom) res()
ajax.post('<%=api.url("ping_node")%>', {
index: dom.indexs,
address: dom.address,
port: dom.port
},
function(x, result) {
if (x && x.status == 200) {
var strs = dom.indexs.split(",");
for (var i = 0; i < strs.length; i++) {
if (result.ping == null || result.ping.trim() == "") {
ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
} else {
var ping = parseInt(result.ping);
if (ping < 100)
ping_value[strs[i]].innerHTML = "<font style='color:green'>" + result.ping + " ms" + "</font>";
else if (ping < 200)
ping_value[strs[i]].innerHTML = "<font style='color:#fb9a05'>" + result.ping + " ms" + "</font>";
else if (ping >= 200)
ping_value[strs[i]].innerHTML = "<font style='color:red'>" + result.ping + " ms" + "</font>";
/* 自动Ping */
if (auto_detection_time == "icmp" || auto_detection_time == "tcping") {
var nodes = [];
const ping_value = document.getElementsByClassName(auto_detection_time == "tcping" ? 'tcping_value' : 'ping_value');
for (var i = 0; i < ping_value.length; i++) {
var cbi_id = ping_value[i].getAttribute("cbiid");
var full = get_address_full(cbi_id);
if (full != null) {
var flag = false;
//当有多个相同地址和端口时合在一起
for (var j = 0; j < nodes.length; j++) {
if (nodes[j].address == full.address && nodes[j].port == full.port) {
nodes[j].indexs = nodes[j].indexs + "," + i;
flag = true;
break;
}
}
if (flag)
continue;
nodes.push({
indexs: i + "",
address: full.address,
port: full.port
});
}
}
const _xhr = (index) => {
return new Promise((res) => {
const dom = nodes[index];
if (!dom) res()
ajax.post('<%=api.url("ping_node")%>', {
index: dom.indexs,
address: dom.address,
port: dom.port,
type: auto_detection_time
},
function(x, result) {
if (x && x.status == 200) {
var strs = dom.indexs.split(",");
for (var i = 0; i < strs.length; i++) {
if (result.ping == null || result.ping.trim() == "") {
ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
} else {
var ping = parseInt(result.ping);
if (ping < 100)
ping_value[strs[i]].innerHTML = "<font style='color:green'>" + result.ping + " ms" + "</font>";
else if (ping < 200)
ping_value[strs[i]].innerHTML = "<font style='color:#fb9a05'>" + result.ping + " ms" + "</font>";
else if (ping >= 200)
ping_value[strs[i]].innerHTML = "<font style='color:red'>" + result.ping + " ms" + "</font>";
}
}
}
}
res();
},
5000,
function(x) {
var strs = dom.indexs.split(",");
for (var i = 0; i < strs.length; i++) {
ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
}
res();
}
);
})
}
let task = -1;
const thread = () => {
task = task + 1
if (nodes[task]) {
_xhr(task).then(thread);
}
}
for (let i = 0; i < 20; i++) {
thread()
}
/* 递归单请求方法
var index = 0;
function auto_ping() {
if (index >= nodes.length) {
return;
}
var indexs = nodes[index].indexs;
var address = nodes[index].address;
var port = nodes[index].port;
ajax.post('<%=api.url("ping_node")%>', {
index: indexs,
address: address,
port: port
},
function(x, result) {
if (x && x.status == 200) {
var strs = indexs.split(",");
for (var i = 0; i < strs.length; i++) {
if (result.ping == null || result.ping.trim() == "") {
res();
},
5000,
function(x) {
var strs = dom.indexs.split(",");
for (var i = 0; i < strs.length; i++) {
ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
} else {
var ping = parseInt(result.ping);
if (ping < 100)
ping_value[strs[i]].innerHTML = "<font style='color:green'>" + result.ping + " ms" + "</font>";
else if (ping < 200)
ping_value[strs[i]].innerHTML = "<font style='color:#fb9a05'>" + result.ping + " ms" + "</font>";
else if (ping >= 200)
ping_value[strs[i]].innerHTML = "<font style='color:red'>" + result.ping + " ms" + "</font>";
}
res();
}
}
index++;
return auto_ping();
},
function(x) {
var strs = indexs.split(",");
for (var i = 0; i < strs.length; i++) {
ping_value[strs[i]].innerHTML = "<font style='color:red'><%:Timeout%></font>";
}
index++;
return auto_ping();
},
);
);
})
}
let task = -1;
const thread = () => {
task = task + 1
if (nodes[task]) {
_xhr(task).then(thread);
}
}
for (let i = 0; i < 20; i++) {
thread()
}
}
auto_ping();
*/
var edit_btn = document.getElementById("cbi-passwall-nodes").getElementsByClassName("cbi-button cbi-button-edit");
for (var i = 0; i < edit_btn.length; i++) {

View File

@ -298,8 +298,11 @@ msgstr "添加节点"
msgid "Add the node via the link"
msgstr "通过链接添加节点"
msgid "SS/SSR/Vmess/VLESS/Trojan/Hysteria Link"
msgstr "SS/SSR/Vmess/VLESS/Trojan/Hysteria 链接"
msgid "Share Link"
msgstr "分享链接"
msgid "Not a subscription link!!!"
msgstr "不是订阅链接!!!"
msgid "Please enter the correct link."
msgstr "请输入正确的链接。"
@ -550,26 +553,17 @@ msgstr "加密"
msgid "Latency"
msgstr "延迟"
msgid "Show Add Mode"
msgstr "显示添加方式"
msgid "Show Group"
msgstr "显示组"
msgid "Group"
msgstr "组"
msgid "Auto Ping"
msgstr "自动Ping"
msgid "Concise display nodes"
msgstr "简洁显示节点"
msgid "Automatic detection delay"
msgstr "自动检测延迟"
msgid "Show server address and port"
msgstr "显示服务器地址和端口"
msgid "Availability test"
msgstr "可用性测试"
msgid "URL Test"
msgstr "URL 测试"
msgid "Test"
msgstr "测试"
msgid "Node num"
msgstr "节点数量"
@ -751,8 +745,8 @@ msgstr "内置实现"
msgid "Health Check Inter"
msgstr "健康检查节点间隔时间"
msgid "When the availability test is used, the load balancing node will be converted into a Socks node. when node list set customizing, must be a Socks node, otherwise the health check will be invalid."
msgstr "当使用可用性测试时负载均衡节点将转换成Socks节点。下面的节点列表自定义时必须为Socks节点否则健康检查将无效。"
msgid "When the URL test is used, the load balancing node will be converted into a Socks node. when node list set customizing, must be a Socks node, otherwise the health check will be invalid."
msgstr "当使用URL测试时负载均衡节点将转换成Socks节点。下面的节点列表自定义时必须为Socks节点否则健康检查将无效。"
msgid "Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group."
msgstr "添加节点指定出口功能是为多WAN用户准备的。负载比重范围1-256。多个主服务器可以负载均衡备用只有在主服务器离线时才会启用可以设置多个组负载均衡端口相同则为一组。"

View File

@ -52,7 +52,8 @@ config global_singbox
option geosite_url 'https://github.com/MetaCubeX/meta-rules-dat/releases/download/latest/geosite.db'
config global_other
option nodes_ping 'auto_ping tcping'
option auto_detection_time 'tcping'
option show_node_info '0'
config global_rules
option auto_update '0'