forked from KNEMC/KLALB
feat(config): switch webPort to URI-style webListen address
- replace integer webPort with MultiProtocolSocketAddress webListen (default: http://0.0.0.0:4665) in controller config - rename Swing UI item to "Web API 监听地址" and validate as full URI - update WebServer binding to honor configured host and port - normalize legacy webPort integers to http://0.0.0.0:<port> on load and keep JSON API backward compatibility - update i18n keys in zh_CN and en_US resource bundles - update root klalb-config.json and AGENTS.md documentation
This commit is contained in:
@@ -114,5 +114,5 @@ multifill=Multi-Core - Fill Cores Sequentially (Recommended for general-purpose
|
||||
multiscatter=Multi-Core - Spread Load Evenly (Optimized for multi-socket NUMA architectures)
|
||||
webapisettings=Web API settings
|
||||
enablewebapi=Enable Web API
|
||||
webport=Web port
|
||||
invaildwebport=Invalid web port number
|
||||
weblistenaddr=Web API listen address
|
||||
invaildweblistenaddr=Invalid Web API listen address
|
||||
|
||||
@@ -4,9 +4,9 @@ language=语言
|
||||
basicsettings=基本设置
|
||||
ipv6addr=IPv6地址
|
||||
devicename=设备名称
|
||||
devicedescription=设备描述
|
||||
devicedescription=设备描述
|
||||
dnsserver=DNS服务器
|
||||
extraroutes=额外路由
|
||||
extraroutes=额外路由
|
||||
asnumber=AS号码
|
||||
tcplistening=TCP监听端口
|
||||
udplistening=UDP监听端口
|
||||
@@ -111,8 +111,8 @@ performancesettings=性能设置
|
||||
performancestrategy=性能策略
|
||||
singlecore=单核-缓存命中率优先(高能耗比,适合低功耗设备、云机)
|
||||
multifill=多核-负载按顺序填充(适合大多数物理服务器、电脑)
|
||||
multiscatter=多核-负载均匀打散分配(适合特殊的多路NUMA服务器)
|
||||
webapisettings=Web API \u8bbe\u7f6e
|
||||
enablewebapi=\u542f\u7528 Web API
|
||||
webport=Web \u7aef\u53e3
|
||||
invaildwebport=\u65e0\u6548\u7684 Web \u7aef\u53e3\u53f7
|
||||
multiscatter=多核-负载均匀打散分配(适合特殊的多路NUMA服务器)
|
||||
webapisettings=Web API 设置
|
||||
enablewebapi=启用 Web API
|
||||
weblistenaddr=Web API 监听地址:端口
|
||||
invaildweblistenaddr=无效的 Web API 监听地址:端口
|
||||
|
||||
@@ -7,8 +7,9 @@ import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
@@ -78,11 +79,16 @@ public class KLALBConfigItem {
|
||||
* denyConnectionQuery/denyLineTableQuery → denyExternalEndpointQuery,
|
||||
* denyConnectionBroadcast/denyLineTableBroadcast → denyExternalEndpointBroadcast。
|
||||
*/
|
||||
private void normalizeLegacyControllerKeys(JsonObject jobj) {
|
||||
renameLegacyKey(jobj,"externalEndpoints","openConnections","OpenConnections","lineTable","LineTable");
|
||||
renameLegacyKey(jobj,"denyExternalEndpointQuery","denyConnectionQuery","denyLineTableQuery");
|
||||
renameLegacyKey(jobj,"denyExternalEndpointBroadcast","denyConnectionBroadcast","denyLineTableBroadcast");
|
||||
}
|
||||
private void normalizeLegacyControllerKeys(JsonObject jobj) {
|
||||
renameLegacyKey(jobj,"externalEndpoints","openConnections","OpenConnections","lineTable","LineTable");
|
||||
renameLegacyKey(jobj,"denyExternalEndpointQuery","denyConnectionQuery","denyLineTableQuery");
|
||||
renameLegacyKey(jobj,"denyExternalEndpointBroadcast","denyConnectionBroadcast","denyLineTableBroadcast");
|
||||
if (!jobj.has("webListen") && jobj.has("webPort") && !jobj.get("webPort").isJsonNull()) {
|
||||
int port = jobj.get("webPort").getAsInt();
|
||||
jobj.add("webListen", new JsonPrimitive("http://0.0.0.0:" + port));
|
||||
}
|
||||
jobj.remove("webPort");
|
||||
}
|
||||
|
||||
private void renameLegacyKey(JsonObject jobj, String newKey, String... legacyKeys) {
|
||||
if (jobj.has(newKey)) {
|
||||
|
||||
@@ -35,7 +35,7 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
|
||||
private String DeviceName;
|
||||
private String DeviceDescription;
|
||||
private boolean webUI = false;
|
||||
private int webPort = 4665;
|
||||
private MultiProtocolSocketAddress webListen = new MultiProtocolSocketAddress("http", "0.0.0.0", 4665);
|
||||
|
||||
public boolean isEnableTUN() {
|
||||
return enableTUN;
|
||||
@@ -53,12 +53,12 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
|
||||
this.webUI = webUI;
|
||||
}
|
||||
|
||||
public int getWebPort() {
|
||||
return webPort;
|
||||
}
|
||||
|
||||
public void setWebPort(int webPort) {
|
||||
this.webPort = webPort;
|
||||
public MultiProtocolSocketAddress getWebListen() {
|
||||
return webListen;
|
||||
}
|
||||
|
||||
public void setWebListen(MultiProtocolSocketAddress webListen) {
|
||||
this.webListen = webListen;
|
||||
}
|
||||
|
||||
public String getPerformanceStrategy() {
|
||||
@@ -397,10 +397,12 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
|
||||
", enableTUN=" + enableTUN +
|
||||
", TUNName='" + TUNName + '\'' +
|
||||
", performanceStrategy='" + performanceStrategy + '\'' +
|
||||
", DeviceName='" + DeviceName + '\'' +
|
||||
", DeviceDescription='" + DeviceDescription + '\'' +
|
||||
", NetworkInterfaceExcepts=" + NetworkInterfaceExcepts +
|
||||
'}';
|
||||
", DeviceName='" + DeviceName + '\'' +
|
||||
", DeviceDescription='" + DeviceDescription + '\'' +
|
||||
", NetworkInterfaceExcepts=" + NetworkInterfaceExcepts +
|
||||
", webUI=" + webUI +
|
||||
", webListen=" + webListen +
|
||||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -408,11 +410,11 @@ public class KLALBControllerConfigItem extends KLALBConfigItem {
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (!super.equals(o)) return false;
|
||||
KLALBControllerConfigItem that = (KLALBControllerConfigItem) o;
|
||||
return nogui == that.nogui && enableTUN == that.enableTUN && webUI == that.webUI && denyExternalEndpointQuery == that.denyExternalEndpointQuery && denyExternalEndpointBroadcast == that.denyExternalEndpointBroadcast && Double.compare(burstLimit, that.burstLimit) == 0 && Double.compare(delayUpperBound, that.delayUpperBound) == 0 && Double.compare(delayLowerBound, that.delayLowerBound) == 0 && nagleDelayTime == that.nagleDelayTime && linkNagleDelayTime == that.linkNagleDelayTime && linkConnectionsCount == that.linkConnectionsCount && webPort == that.webPort && Objects.equals(language, that.language) && Objects.equals(VirtualAddress, that.VirtualAddress) && Objects.equals(VirtualASN, that.VirtualASN) && Objects.equals(DNS, that.DNS) && Objects.equals(TCPListen, that.TCPListen) && Objects.equals(UDPListen, that.UDPListen) && Objects.equals(VirtualSocketName, that.VirtualSocketName) && Objects.equals(externalEndpoints, that.externalEndpoints) && Objects.equals(autoConnections, that.autoConnections) && Objects.equals(ntpServers, that.ntpServers) && Objects.equals(ExtraRoutes, that.ExtraRoutes) && Objects.equals(congestionAlgorithm, that.congestionAlgorithm) && Objects.equals(TUNName, that.TUNName) && Objects.equals(performanceStrategy, that.performanceStrategy) && Objects.equals(DeviceName, that.DeviceName) && Objects.equals(DeviceDescription, that.DeviceDescription) && Objects.equals(NetworkInterfaceExcepts, that.NetworkInterfaceExcepts);
|
||||
return nogui == that.nogui && enableTUN == that.enableTUN && webUI == that.webUI && denyExternalEndpointQuery == that.denyExternalEndpointQuery && denyExternalEndpointBroadcast == that.denyExternalEndpointBroadcast && Double.compare(burstLimit, that.burstLimit) == 0 && Double.compare(delayUpperBound, that.delayUpperBound) == 0 && Double.compare(delayLowerBound, that.delayLowerBound) == 0 && nagleDelayTime == that.nagleDelayTime && linkNagleDelayTime == that.linkNagleDelayTime && linkConnectionsCount == that.linkConnectionsCount && Objects.equals(webListen, that.webListen) && Objects.equals(language, that.language) && Objects.equals(VirtualAddress, that.VirtualAddress) && Objects.equals(VirtualASN, that.VirtualASN) && Objects.equals(DNS, that.DNS) && Objects.equals(TCPListen, that.TCPListen) && Objects.equals(UDPListen, that.UDPListen) && Objects.equals(VirtualSocketName, that.VirtualSocketName) && Objects.equals(externalEndpoints, that.externalEndpoints) && Objects.equals(autoConnections, that.autoConnections) && Objects.equals(ntpServers, that.ntpServers) && Objects.equals(ExtraRoutes, that.ExtraRoutes) && Objects.equals(congestionAlgorithm, that.congestionAlgorithm) && Objects.equals(TUNName, that.TUNName) && Objects.equals(performanceStrategy, that.performanceStrategy) && Objects.equals(DeviceName, that.DeviceName) && Objects.equals(DeviceDescription, that.DeviceDescription) && Objects.equals(NetworkInterfaceExcepts, that.NetworkInterfaceExcepts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), language, nogui, VirtualAddress, VirtualASN, DNS, TCPListen, UDPListen, VirtualSocketName, externalEndpoints, autoConnections, ntpServers, ExtraRoutes, denyExternalEndpointQuery, denyExternalEndpointBroadcast, congestionAlgorithm, burstLimit, delayUpperBound, delayLowerBound, nagleDelayTime, linkNagleDelayTime, linkConnectionsCount, enableTUN, TUNName, performanceStrategy, DeviceName, DeviceDescription, NetworkInterfaceExcepts, webUI, webPort);
|
||||
return Objects.hash(super.hashCode(), language, nogui, VirtualAddress, VirtualASN, DNS, TCPListen, UDPListen, VirtualSocketName, externalEndpoints, autoConnections, ntpServers, ExtraRoutes, denyExternalEndpointQuery, denyExternalEndpointBroadcast, congestionAlgorithm, burstLimit, delayUpperBound, delayLowerBound, nagleDelayTime, linkNagleDelayTime, linkConnectionsCount, enableTUN, TUNName, performanceStrategy, DeviceName, DeviceDescription, NetworkInterfaceExcepts, webUI, webListen);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -108,12 +108,12 @@ public class KLALBMain {
|
||||
case "web":
|
||||
if(sc.length >= 2) {
|
||||
String action = sc[1].toLowerCase();
|
||||
if("start".equals(action)) {
|
||||
int p = 4665;
|
||||
if(sc.length >= 3) {
|
||||
try { p = Integer.parseInt(sc[2]); } catch (NumberFormatException ignored) {}
|
||||
} else if(kpcje.getControllerConfig() != null && kpcje.getControllerConfig().getWebPort() > 0) {
|
||||
p = kpcje.getControllerConfig().getWebPort();
|
||||
if("start".equals(action)) {
|
||||
int p = 4665;
|
||||
if(sc.length >= 3) {
|
||||
try { p = Integer.parseInt(sc[2]); } catch (NumberFormatException ignored) {}
|
||||
} else if(kpcje.getControllerConfig() != null && kpcje.getControllerConfig().getWebListen() != null) {
|
||||
p = kpcje.getControllerConfig().getWebListen().getPort();
|
||||
}
|
||||
try {
|
||||
kpcje.enableWebServer(p);
|
||||
|
||||
@@ -84,18 +84,20 @@ public class KLALBProxySystem {
|
||||
public KLALBProxySystem() {
|
||||
}
|
||||
|
||||
public void enableWebServer() throws IOException {
|
||||
int port = 4665;
|
||||
KLALBControllerConfigItem cci = getControllerConfig();
|
||||
if (cci != null && cci.getWebPort() > 0) {
|
||||
port = cci.getWebPort();
|
||||
}
|
||||
enableWebServer(port);
|
||||
}
|
||||
|
||||
public void enableWebServer(int port) throws IOException {
|
||||
if (webServer == null) {
|
||||
webServer = new KLALBWebServer(this, port);
|
||||
public void enableWebServer() throws IOException {
|
||||
KLALBControllerConfigItem cci = getControllerConfig();
|
||||
MultiProtocolSocketAddress listen = cci == null || cci.getWebListen() == null
|
||||
? new MultiProtocolSocketAddress("http", "0.0.0.0", 4665) : cci.getWebListen();
|
||||
enableWebServer(listen);
|
||||
}
|
||||
|
||||
public void enableWebServer(int port) throws IOException {
|
||||
enableWebServer(new MultiProtocolSocketAddress("http", "0.0.0.0", port));
|
||||
}
|
||||
|
||||
public void enableWebServer(MultiProtocolSocketAddress listen) throws IOException {
|
||||
if (webServer == null) {
|
||||
webServer = new KLALBWebServer(this, listen);
|
||||
webServer.start();
|
||||
} else {
|
||||
throw new IllegalStateException("Web server already enabled!");
|
||||
|
||||
@@ -76,7 +76,7 @@ public class KLALBStateGUI3 extends XFrame {
|
||||
private JTextField addressFieldSet; // 地址设置框
|
||||
private JTextField asnFieldSet; // ASN设置框
|
||||
private JTextField tunDeviceName; // 虚拟网卡名称设置框
|
||||
private JTextField webPortSet; // Web API 端口设置框
|
||||
private JTextField webListenSet; // Web API 监听地址设置框
|
||||
private NetworkGraphPanel graph; // 网络图面板
|
||||
private JTextField textFieldLocate; // 定位地址输入框
|
||||
private JTextField asnField2; // ASN显示框
|
||||
@@ -917,10 +917,10 @@ public class KLALBStateGUI3 extends XFrame {
|
||||
webApiEnabled=webApic.getCheckBox();
|
||||
settings.getView().add(webApic);
|
||||
|
||||
TextSettingItem webPort = new TextSettingItem(UIEnv.getRsb().getString("webport"),
|
||||
CONST.itemwidth, CONST.settingheight);
|
||||
webPortSet = webPort.getTextField();
|
||||
settings.getView().add(webPort);
|
||||
TextSettingItem webListen = new TextSettingItem(UIEnv.getRsb().getString("weblistenaddr"),
|
||||
CONST.itemwidth, CONST.settingheight);
|
||||
webListenSet = webListen.getTextField();
|
||||
settings.getView().add(webListen);
|
||||
|
||||
//性能设置标题
|
||||
|
||||
@@ -1158,23 +1158,19 @@ public class KLALBStateGUI3 extends XFrame {
|
||||
kck.setTUNName(tunNameText);
|
||||
}
|
||||
|
||||
// 保存Web API设置
|
||||
kck.setWebUI(webApiEnabled.isSelected());
|
||||
String webPortText = webPortSet.getText().trim();
|
||||
if (webPortText.equals("")) {
|
||||
kck.setWebPort(4665);
|
||||
} else {
|
||||
try {
|
||||
int wp = Integer.parseInt(webPortText);
|
||||
if (wp < 0 || wp > 65535) {
|
||||
throw new NumberFormatException("out of range");
|
||||
}
|
||||
kck.setWebPort(wp);
|
||||
} catch (NumberFormatException e) {
|
||||
e.printStackTrace();
|
||||
JOptionPane.showMessageDialog(this, UIEnv.getRsb().getString("invaildwebport"),
|
||||
UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
// 保存Web API设置
|
||||
kck.setWebUI(webApiEnabled.isSelected());
|
||||
String webListenText = webListenSet.getText().trim();
|
||||
if (webListenText.equals("")) {
|
||||
kck.setWebListen(new MultiProtocolSocketAddress("http", "0.0.0.0", 4665));
|
||||
} else {
|
||||
try {
|
||||
kck.setWebListen(new MultiProtocolSocketAddress(webListenText));
|
||||
} catch (RuntimeException e) {
|
||||
e.printStackTrace();
|
||||
JOptionPane.showMessageDialog(this, UIEnv.getRsb().getString("invaildweblistenaddr"),
|
||||
UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1578,9 +1574,10 @@ public class KLALBStateGUI3 extends XFrame {
|
||||
String tunname=kck.getTUNName();
|
||||
tunDeviceName.setText(tunname!=null?tunname:"");
|
||||
|
||||
// 加载Web API设置
|
||||
webApiEnabled.setSelected(kck.isWebUI());
|
||||
webPortSet.setText(Integer.toString(kck.getWebPort()));
|
||||
// 加载Web API设置
|
||||
webApiEnabled.setSelected(kck.isWebUI());
|
||||
webListenSet.setText(kck.getWebListen() != null ? kck.getWebListen().toString()
|
||||
: "http://0.0.0.0:4665");
|
||||
|
||||
// 加载TCP监听
|
||||
MultiProtocolSocketAddress mpat = kck.getTCPListen();
|
||||
@@ -1768,4 +1765,4 @@ public class KLALBStateGUI3 extends XFrame {
|
||||
KLALBStateGUI3 kcg = new KLALBStateGUI3(new KLALBController());
|
||||
kcg.setVisible(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ import org.kne.cloud.network.srv6.SRv6Router;
|
||||
*/
|
||||
public class KLALBWebServer {
|
||||
private final KLALBProxySystem proxySystem;
|
||||
private final int port;
|
||||
private final MultiProtocolSocketAddress listen;
|
||||
private HttpServer server;
|
||||
private final Gson gson;
|
||||
private final ScheduledExecutorService sseExecutor = Executors.newSingleThreadScheduledExecutor(r -> {
|
||||
@@ -43,15 +43,21 @@ public class KLALBWebServer {
|
||||
private final AtomicBoolean running = new AtomicBoolean(false);
|
||||
|
||||
public KLALBWebServer(KLALBProxySystem proxySystem, int port) {
|
||||
this(proxySystem, new MultiProtocolSocketAddress("http", "0.0.0.0", port));
|
||||
}
|
||||
|
||||
public KLALBWebServer(KLALBProxySystem proxySystem, MultiProtocolSocketAddress listen) {
|
||||
this.proxySystem = proxySystem;
|
||||
this.port = port;
|
||||
this.listen = listen;
|
||||
this.gson = proxySystem.getGson();
|
||||
}
|
||||
|
||||
public synchronized void start() throws IOException {
|
||||
if (running.get()) return;
|
||||
|
||||
server = HttpServer.create(new InetSocketAddress(port), 0);
|
||||
InetSocketAddress socketAddress = "0.0.0.0".equals(listen.getHost())
|
||||
? new InetSocketAddress(listen.getPort()) : listen.getSocketAddress();
|
||||
server = HttpServer.create(socketAddress, 0);
|
||||
server.setExecutor(Executors.newVirtualThreadPerTaskExecutor());
|
||||
|
||||
// API Contexts
|
||||
@@ -72,7 +78,7 @@ public class KLALBWebServer {
|
||||
running.set(true);
|
||||
startSseBroadcaster();
|
||||
|
||||
System.out.println("KLALB Web Dashboard started at http://localhost:" + port);
|
||||
System.out.println("KLALB Web Dashboard started at " + listen);
|
||||
}
|
||||
|
||||
public synchronized void stop() {
|
||||
@@ -97,7 +103,7 @@ public class KLALBWebServer {
|
||||
}
|
||||
|
||||
public int getPort() {
|
||||
return port;
|
||||
return listen.getPort();
|
||||
}
|
||||
|
||||
private void setCorsHeaders(HttpExchange exchange) {
|
||||
@@ -605,8 +611,10 @@ public class KLALBWebServer {
|
||||
current.setWebUI(json.get("webUI").getAsBoolean());
|
||||
}
|
||||
|
||||
if (json.has("webPort")) {
|
||||
current.setWebPort(json.get("webPort").getAsInt());
|
||||
if (json.has("webListen") && !json.get("webListen").isJsonNull()) {
|
||||
current.setWebListen(new MultiProtocolSocketAddress(json.get("webListen").getAsString()));
|
||||
} else if (json.has("webPort")) {
|
||||
current.setWebListen(new MultiProtocolSocketAddress("http", "0.0.0.0", json.get("webPort").getAsInt()));
|
||||
}
|
||||
|
||||
if (json.has("nogui")) {
|
||||
|
||||
Reference in New Issue
Block a user