forked from KNEMC/KLALB
Revert "fix(config): sync Swing settings after Web updates"
This reverts commit b6acc6d509.
This commit is contained in:
@@ -32,8 +32,8 @@ KLALB is a Java SRv6/load-balancing system. Start at `org.kne.cloud.network.klal
|
|||||||
## Important Boundaries
|
## Important Boundaries
|
||||||
|
|
||||||
- `KLALBConfigItem` is a polymorphic JSON array keyed by case-sensitive `Type`. New types need serializer and deserializer support; preserve unknown items' raw JSON.
|
- `KLALBConfigItem` is a polymorphic JSON array keyed by case-sensitive `Type`. New types need serializer and deserializer support; preserve unknown items' raw JSON.
|
||||||
- `/api/config` parses fields and legacy aliases explicitly. Web and Swing writes must use `KLALBProxySystem`'s revision-checked detached-candidate commit path, never mutate the canonical config directly.
|
- `/api/config` is field-by-field parsing, not whole-object Gson mapping. Keep legacy key aliases in sync with new fields.
|
||||||
- Vendored Gson is 2.1: serialize HTTP `JsonElement` values with `toString()`; serialize configuration through the configured pretty-print Gson path.
|
- Vendored Gson is `2.1`: responses that are `JsonElement` instances must be serialized with `JsonElement.toString()`, not reflective `gson.toJson(Object)`.
|
||||||
- UI strings use `UIEnv.getRsb()`; add keys to both `src/klalb_zh_CN.properties` and `src/klalb_en_US.properties`.
|
- UI strings use `UIEnv.getRsb()`; add keys to both `src/klalb_zh_CN.properties` and `src/klalb_en_US.properties`.
|
||||||
- `KLALBController.PublishedNodeInfo` is the thread-safe node-info source. Publish profile, effective external endpoints, and extra routes through the controller so snapshots and update flags remain coherent. Peer queries are separate profile, endpoint, and extra-route requests; use `NodeInfoQueryCoordinator` when a consumer needs an aggregate detail result.
|
- `KLALBController.PublishedNodeInfo` is the thread-safe node-info source. Publish profile, effective external endpoints, and extra routes through the controller so snapshots and update flags remain coherent. Peer queries are separate profile, endpoint, and extra-route requests; use `NodeInfoQueryCoordinator` when a consumer needs an aggregate detail result.
|
||||||
- `RouterInfo` retains an empty legacy UTF slot. `RouterInfoPacket` appends optional update flags behind a marker; treat binary codec changes as mesh-compatibility work and preserve old-reader behavior.
|
- `RouterInfo` retains an empty legacy UTF slot. `RouterInfoPacket` appends optional update flags behind a marker; treat binary codec changes as mesh-compatibility work and preserve old-reader behavior.
|
||||||
|
|||||||
@@ -35,12 +35,6 @@ reconnectall=Reconnect All
|
|||||||
remotelines=Remote lines
|
remotelines=Remote lines
|
||||||
settings=Settings
|
settings=Settings
|
||||||
saveconfigsuccess=Save config success
|
saveconfigsuccess=Save config success
|
||||||
configexternalupdate=The configuration was updated by another source.
|
|
||||||
configreload=Reload
|
|
||||||
configcontinue=Continue editing
|
|
||||||
configsaveconflict=Save failed: the configuration was updated. Reload and try again.
|
|
||||||
configsavefailed=Failed to save configuration.
|
|
||||||
configconflicttitle=Configuration conflict
|
|
||||||
warning=Warning
|
warning=Warning
|
||||||
invaildipv6addr=IPv6 address:Invaild Input
|
invaildipv6addr=IPv6 address:Invaild Input
|
||||||
invailddnsserver=DNS server:Invaild Input
|
invailddnsserver=DNS server:Invaild Input
|
||||||
|
|||||||
@@ -35,12 +35,6 @@ reconnectall=全部重连
|
|||||||
remotelines=远程链路
|
remotelines=远程链路
|
||||||
settings=设置
|
settings=设置
|
||||||
saveconfigsuccess=保存配置成功
|
saveconfigsuccess=保存配置成功
|
||||||
configexternalupdate=配置已被其他来源更新。
|
|
||||||
configreload=重新加载
|
|
||||||
configcontinue=继续编辑
|
|
||||||
configsaveconflict=保存失败:配置已被更新,请重新加载后再试。
|
|
||||||
configsavefailed=保存配置失败。
|
|
||||||
configconflicttitle=配置冲突
|
|
||||||
warning=警告
|
warning=警告
|
||||||
invaildipv6addr=IPv6地址:非法输入
|
invaildipv6addr=IPv6地址:非法输入
|
||||||
invailddnsserver=DNS服务器:非法输入
|
invailddnsserver=DNS服务器:非法输入
|
||||||
|
|||||||
@@ -583,63 +583,7 @@ public class KLALBController {
|
|||||||
|
|
||||||
private KLALBRoutingProtocolAPIClient apiClient;
|
private KLALBRoutingProtocolAPIClient apiClient;
|
||||||
|
|
||||||
private volatile KLALBControllerConfigItem configItem;
|
private KLALBControllerConfigItem configItem;
|
||||||
|
|
||||||
private static <T> List<T> copyConfigList(List<T> values) {
|
|
||||||
return values == null ? null : new ArrayList<T>(values);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static KLALBControllerConfigItem copyConfigItem(KLALBControllerConfigItem source) {
|
|
||||||
KLALBControllerConfigItem copy = new KLALBControllerConfigItem();
|
|
||||||
copy.setLanguage(source.getLanguage());
|
|
||||||
copy.setNogui(source.isNogui());
|
|
||||||
copy.setVirtualAddress(source.getVirtualAddress());
|
|
||||||
copy.setVirtualASN(source.getVirtualASN());
|
|
||||||
copy.setDNS(copyConfigList(source.getDNS()));
|
|
||||||
copy.setTCPListen(source.getTCPListen());
|
|
||||||
copy.setUDPListen(source.getUDPListen());
|
|
||||||
copy.setVirtualSocketName(source.getVirtualSocketName());
|
|
||||||
copy.setExternalEndpoints(copyConfigList(source.getExternalEndpoints()));
|
|
||||||
copy.setAutoConnections(copyConfigList(source.getAutoConnections()));
|
|
||||||
copy.setNtpServers(copyConfigList(source.getNtpServers()));
|
|
||||||
copy.setExtraRoutes(copyConfigList(source.getExtraRoutes()));
|
|
||||||
copy.setDenyExternalEndpointQuery(source.isDenyExternalEndpointQuery());
|
|
||||||
copy.setDenyExternalEndpointBroadcast(source.isDenyExternalEndpointBroadcast());
|
|
||||||
copy.setCongestionAlgorithm(source.getCongestionAlgorithm());
|
|
||||||
copy.setBurstLimit(source.getBurstLimit());
|
|
||||||
copy.setDelayUpperBound(source.getDelayUpperBound());
|
|
||||||
copy.setDelayLowerBound(source.getDelayLowerBound());
|
|
||||||
copy.setNagleDelayTime(source.getNagleDelayTime());
|
|
||||||
copy.setLinkNagleDelayTime(source.getLinkNagleDelayTime());
|
|
||||||
copy.setLinkConnectionsCount(source.getLinkConnectionsCount());
|
|
||||||
copy.setEnableTUN(source.isEnableTUN());
|
|
||||||
copy.setTUNName(source.getTUNName());
|
|
||||||
copy.setPerformanceStrategy(source.getPerformanceStrategy());
|
|
||||||
copy.setDeviceName(source.getDeviceName());
|
|
||||||
copy.setDeviceDescription(source.getDeviceDescription());
|
|
||||||
copy.setNetworkInterfaceExcepts(copyConfigList(source.getNetworkInterfaceExcepts()));
|
|
||||||
copy.setWebUI(source.isWebUI());
|
|
||||||
copy.setWebListen(source.getWebListen());
|
|
||||||
return copy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void applyConfigItem(KLALBControllerConfigItem committedConfigItem) {
|
|
||||||
if (committedConfigItem == null) {
|
|
||||||
throw new IllegalArgumentException("Controller configuration is required");
|
|
||||||
}
|
|
||||||
KLALBControllerConfigItem detachedConfigItem = copyConfigItem(committedConfigItem);
|
|
||||||
synchronized (externalEndpoints) {
|
|
||||||
configItem = detachedConfigItem;
|
|
||||||
if (srv6Router != null) {
|
|
||||||
PerformanceStrategy strategy = PerformanceStrategy.fromDescription(detachedConfigItem.getPerformanceStrategy());
|
|
||||||
if (strategy != null) {
|
|
||||||
srv6Router.setPerformanceStrategy(strategy);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
publishNodeInfoLocked(detachedConfigItem.getDeviceName(), detachedConfigItem.getDeviceDescription(),
|
|
||||||
detachedConfigItem.getExternalEndpoints(), detachedConfigItem.getExtraRoutes());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addRemoteLines(List<MultiProtocolSocketAddress> select) {
|
public void addRemoteLines(List<MultiProtocolSocketAddress> select) {
|
||||||
for (MultiProtocolSocketAddress target : select) {
|
for (MultiProtocolSocketAddress target : select) {
|
||||||
|
|||||||
@@ -8,17 +8,7 @@ import java.io.Reader;
|
|||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.nio.file.AtomicMoveNotSupportedException;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.StandardCopyOption;
|
|
||||||
import java.nio.file.StandardOpenOption;
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
|
||||||
import java.util.concurrent.CopyOnWriteArraySet;
|
|
||||||
import java.util.function.Consumer;
|
|
||||||
|
|
||||||
import org.kne.cloud.network.*;
|
import org.kne.cloud.network.*;
|
||||||
import org.kne.cloud.network.klalb.ui.KLALBStateGUI3;
|
import org.kne.cloud.network.klalb.ui.KLALBStateGUI3;
|
||||||
@@ -30,7 +20,6 @@ import java.util.Set;
|
|||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.google.gson.JsonArray;
|
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
import com.google.gson.JsonDeserializer;
|
import com.google.gson.JsonDeserializer;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
@@ -41,81 +30,12 @@ import com.google.gson.JsonSerializer;
|
|||||||
import com.google.gson.JsonParser;
|
import com.google.gson.JsonParser;
|
||||||
|
|
||||||
public class KLALBProxySystem {
|
public class KLALBProxySystem {
|
||||||
public enum ConfigChangeSource {
|
|
||||||
WEB, SWING
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class ControllerConfigSnapshot {
|
|
||||||
private final long revision;
|
|
||||||
private final String controllerJson;
|
|
||||||
|
|
||||||
private ControllerConfigSnapshot(long revision, String controllerJson) {
|
|
||||||
this.revision = revision;
|
|
||||||
this.controllerJson = controllerJson;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getRevision() {
|
|
||||||
return revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getControllerJson() {
|
|
||||||
return controllerJson;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class ConfigChangeEvent {
|
|
||||||
private final ControllerConfigSnapshot snapshot;
|
|
||||||
private final ConfigChangeSource source;
|
|
||||||
|
|
||||||
private ConfigChangeEvent(ControllerConfigSnapshot snapshot, ConfigChangeSource source) {
|
|
||||||
this.snapshot = snapshot;
|
|
||||||
this.source = source;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ControllerConfigSnapshot getSnapshot() {
|
|
||||||
return snapshot;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigChangeSource getSource() {
|
|
||||||
return source;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final class CommitResult {
|
|
||||||
private final boolean success;
|
|
||||||
private final long revision;
|
|
||||||
private final ControllerConfigSnapshot snapshot;
|
|
||||||
|
|
||||||
private CommitResult(boolean success, long revision, ControllerConfigSnapshot snapshot) {
|
|
||||||
this.success = success;
|
|
||||||
this.revision = revision;
|
|
||||||
this.snapshot = snapshot;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isSuccess() {
|
|
||||||
return success;
|
|
||||||
}
|
|
||||||
|
|
||||||
public long getRevision() {
|
|
||||||
return revision;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ControllerConfigSnapshot getSnapshot() {
|
|
||||||
return snapshot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Set<Proxy> proxys=new HashSet<>();
|
private Set<Proxy> proxys=new HashSet<>();
|
||||||
private KLALBController klalbController;
|
private KLALBController klalbController;
|
||||||
private KLALBWebServer webServer;
|
private KLALBWebServer webServer;
|
||||||
private KLALBConfig config;
|
private KLALBConfig config;
|
||||||
private Gson gson;
|
private Gson gson;
|
||||||
private File jsonFile;
|
private File jsonFile;
|
||||||
private final Object configLock = new Object();
|
|
||||||
private long configRevision;
|
|
||||||
private volatile ControllerConfigSnapshot controllerConfigSnapshot = new ControllerConfigSnapshot(0L, null);
|
|
||||||
private final CopyOnWriteArraySet<Consumer<ConfigChangeEvent>> configChangeListeners = new CopyOnWriteArraySet<>();
|
|
||||||
private JsonArray rawConfigJson;
|
|
||||||
{
|
{
|
||||||
GsonBuilder gb=new GsonBuilder().setPrettyPrinting();
|
GsonBuilder gb=new GsonBuilder().setPrettyPrinting();
|
||||||
MultiProtocolSocketAddress.registerToGsonBuilder(gb);
|
MultiProtocolSocketAddress.registerToGsonBuilder(gb);
|
||||||
@@ -222,25 +142,11 @@ public class KLALBProxySystem {
|
|||||||
loadConfigJson(new JsonParser().parse(json));
|
loadConfigJson(new JsonParser().parse(json));
|
||||||
}
|
}
|
||||||
public void loadConfigJson(JsonElement json) {
|
public void loadConfigJson(JsonElement json) {
|
||||||
JsonElement rawJson = new JsonParser().parse(json.toString());
|
|
||||||
KLALBConfig config= gson.fromJson(json, KLALBConfig.class);
|
KLALBConfig config= gson.fromJson(json, KLALBConfig.class);
|
||||||
JsonArray rawArray = rawJson instanceof JsonArray ? (JsonArray) rawJson : null;
|
loadConfig(config);
|
||||||
synchronized (configLock) {
|
|
||||||
installConfigLocked(config, rawArray);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public void loadConfig(KLALBConfig config) {
|
public void loadConfig(KLALBConfig config) {
|
||||||
JsonElement rawJson = gson.toJsonTree(config);
|
|
||||||
JsonArray rawArray = rawJson instanceof JsonArray ? (JsonArray) rawJson : null;
|
|
||||||
synchronized (configLock) {
|
|
||||||
installConfigLocked(config, rawArray);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void installConfigLocked(KLALBConfig config, JsonArray rawArray) {
|
|
||||||
this.config=config;
|
this.config=config;
|
||||||
this.configRevision=0L;
|
|
||||||
rawConfigJson=rawArray;
|
|
||||||
for(KLALBConfigItem item:config) {
|
for(KLALBConfigItem item:config) {
|
||||||
if(item instanceof KLALBControllerConfigItem) {
|
if(item instanceof KLALBControllerConfigItem) {
|
||||||
KLALBControllerConfigItem kcci=(KLALBControllerConfigItem) item;
|
KLALBControllerConfigItem kcci=(KLALBControllerConfigItem) item;
|
||||||
@@ -323,171 +229,28 @@ public class KLALBProxySystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
controllerConfigSnapshot = createControllerConfigSnapshotLocked();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void saveConfigToFile() {
|
public void saveConfigToFile() {
|
||||||
synchronized (configLock) {
|
|
||||||
if (jsonFile != null && config != null) {
|
if (jsonFile != null && config != null) {
|
||||||
try {
|
String json = gson.toJson(config);
|
||||||
KLALBControllerConfigItem item = findControllerConfigItemLocked();
|
try (FileWriter fw = new FileWriter(jsonFile)) {
|
||||||
if (item == null) {
|
fw.write(json);
|
||||||
persistConfigJsonLocked(gson.toJson(config));
|
|
||||||
} else {
|
|
||||||
String controllerJson = gson.toJson(item);
|
|
||||||
JsonArray completeConfig = createCompleteConfigJsonLocked(controllerJson);
|
|
||||||
persistConfigJsonLocked(gson.toJson(completeConfig));
|
|
||||||
rawConfigJson = completeConfig;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private KLALBControllerConfigItem findControllerConfigItemLocked() {
|
|
||||||
if (config == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
for (KLALBConfigItem item : config) {
|
|
||||||
if (item instanceof KLALBControllerConfigItem) {
|
|
||||||
return (KLALBControllerConfigItem) item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private int findControllerConfigIndexLocked() {
|
|
||||||
if (config == null) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
for (int i = 0; i < config.size(); i++) {
|
|
||||||
if (config.get(i) instanceof KLALBControllerConfigItem) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
private ControllerConfigSnapshot createControllerConfigSnapshotLocked() {
|
|
||||||
KLALBControllerConfigItem item = findControllerConfigItemLocked();
|
|
||||||
return new ControllerConfigSnapshot(configRevision, item == null ? null : gson.toJson(item));
|
|
||||||
}
|
|
||||||
|
|
||||||
public ControllerConfigSnapshot getControllerConfigSnapshot() {
|
|
||||||
synchronized (configLock) {
|
|
||||||
controllerConfigSnapshot = createControllerConfigSnapshotLocked();
|
|
||||||
return controllerConfigSnapshot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public KLALBControllerConfigItem parseControllerConfigCandidate(ControllerConfigSnapshot snapshot) {
|
|
||||||
if (snapshot == null || snapshot.getControllerJson() == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return gson.fromJson(snapshot.getControllerJson(), KLALBControllerConfigItem.class);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void persistConfigJsonLocked(String json) throws IOException {
|
|
||||||
if (jsonFile == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Path target = jsonFile.toPath().toAbsolutePath();
|
|
||||||
Path parent = target.getParent();
|
|
||||||
Path temporary = Files.createTempFile(parent, target.getFileName().toString(), ".tmp");
|
|
||||||
try {
|
|
||||||
Files.write(temporary, json.getBytes(StandardCharsets.UTF_8), StandardOpenOption.TRUNCATE_EXISTING,
|
|
||||||
StandardOpenOption.WRITE);
|
|
||||||
try {
|
|
||||||
Files.move(temporary, target, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
} catch (AtomicMoveNotSupportedException e) {
|
|
||||||
Files.move(temporary, target, StandardCopyOption.REPLACE_EXISTING);
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
Files.deleteIfExists(temporary);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private JsonArray createCompleteConfigJsonLocked(String controllerJson) throws IOException {
|
|
||||||
JsonElement source = rawConfigJson == null ? gson.toJsonTree(config) : rawConfigJson;
|
|
||||||
if (!(source instanceof JsonArray)) {
|
|
||||||
throw new IOException("Configuration is not an array");
|
|
||||||
}
|
|
||||||
JsonArray sourceArray = (JsonArray) source;
|
|
||||||
int index = findControllerConfigIndexLocked();
|
|
||||||
if (index < 0 || index >= sourceArray.size() || sourceArray.size() != config.size()) {
|
|
||||||
throw new IOException("Configuration item layout changed");
|
|
||||||
}
|
|
||||||
JsonArray mergedConfig = new JsonArray();
|
|
||||||
JsonElement controllerElement = new JsonParser().parse(controllerJson);
|
|
||||||
for (int i = 0; i < sourceArray.size(); i++) {
|
|
||||||
mergedConfig.add(i == index ? controllerElement : sourceArray.get(i));
|
|
||||||
}
|
|
||||||
return mergedConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void addConfigChangeListener(Consumer<ConfigChangeEvent> listener) {
|
|
||||||
configChangeListeners.add(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void removeConfigChangeListener(Consumer<ConfigChangeEvent> listener) {
|
|
||||||
configChangeListeners.remove(listener);
|
|
||||||
}
|
|
||||||
|
|
||||||
public CommitResult commitControllerConfig(long expectedRevision, KLALBControllerConfigItem candidate,
|
|
||||||
ConfigChangeSource source) throws IOException {
|
|
||||||
if (candidate == null || source == null) {
|
|
||||||
throw new IllegalArgumentException("Candidate and source are required");
|
|
||||||
}
|
|
||||||
ConfigChangeEvent event;
|
|
||||||
CommitResult result;
|
|
||||||
synchronized (configLock) {
|
|
||||||
if (expectedRevision != configRevision) {
|
|
||||||
ControllerConfigSnapshot currentSnapshot = createControllerConfigSnapshotLocked();
|
|
||||||
controllerConfigSnapshot = currentSnapshot;
|
|
||||||
return new CommitResult(false, configRevision, currentSnapshot);
|
|
||||||
}
|
|
||||||
int index = findControllerConfigIndexLocked();
|
|
||||||
if (index < 0) {
|
|
||||||
throw new IOException("Controller configuration is missing");
|
|
||||||
}
|
|
||||||
String candidateJson = gson.toJson(candidate);
|
|
||||||
KLALBControllerConfigItem committedCandidate = gson.fromJson(candidateJson,
|
|
||||||
KLALBControllerConfigItem.class);
|
|
||||||
if (PerformanceStrategy.fromDescription(committedCandidate.getPerformanceStrategy()) == null) {
|
|
||||||
throw new IllegalArgumentException("Unknown performanceStrategy: "
|
|
||||||
+ committedCandidate.getPerformanceStrategy());
|
|
||||||
}
|
|
||||||
com.google.gson.JsonArray mergedConfig = createCompleteConfigJsonLocked(candidateJson);
|
|
||||||
persistConfigJsonLocked(gson.toJson(mergedConfig));
|
|
||||||
rawConfigJson = mergedConfig;
|
|
||||||
|
|
||||||
config.set(index, committedCandidate);
|
|
||||||
if (klalbController != null) {
|
|
||||||
klalbController.applyConfigItem(committedCandidate);
|
|
||||||
}
|
|
||||||
configRevision++;
|
|
||||||
controllerConfigSnapshot = createControllerConfigSnapshotLocked();
|
|
||||||
event = new ConfigChangeEvent(controllerConfigSnapshot, source);
|
|
||||||
result = new CommitResult(true, configRevision, controllerConfigSnapshot);
|
|
||||||
}
|
|
||||||
for (Consumer<ConfigChangeEvent> listener : configChangeListeners) {
|
|
||||||
try {
|
|
||||||
listener.accept(event);
|
|
||||||
} catch (Throwable e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private KLALBStateGUI3 kgui;
|
private KLALBStateGUI3 kgui;
|
||||||
public KLALBStateGUI3 getKLALBGUI() {
|
public KLALBStateGUI3 getKLALBGUI() {
|
||||||
if(kgui==null) {
|
if(kgui==null) {
|
||||||
kgui=new KLALBStateGUI3(klalbController);
|
kgui=new KLALBStateGUI3(klalbController);
|
||||||
kgui.bindConfigSystem(this);
|
kgui.loadConfig(config);
|
||||||
|
kgui.setSaveComsumer((cfg)->{
|
||||||
|
saveConfigToFile();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return kgui;
|
return kgui;
|
||||||
}
|
}
|
||||||
@@ -495,6 +258,10 @@ public class KLALBProxySystem {
|
|||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
public KLALBControllerConfigItem getControllerConfig() {
|
public KLALBControllerConfigItem getControllerConfig() {
|
||||||
return parseControllerConfigCandidate(getControllerConfigSnapshot());
|
for(KLALBConfigItem item:config) {
|
||||||
|
if(item instanceof KLALBControllerConfigItem)
|
||||||
|
return (KLALBControllerConfigItem) item;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,80 +106,6 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
// ==================== 配置和回调 ====================
|
// ==================== 配置和回调 ====================
|
||||||
private KLALBConfig config; // 配置文件
|
private KLALBConfig config; // 配置文件
|
||||||
private Consumer<KLALBConfig> saveComsumer; // 保存配置的回调函数
|
private Consumer<KLALBConfig> saveComsumer; // 保存配置的回调函数
|
||||||
private KLALBProxySystem configSystem;
|
|
||||||
private KLALBProxySystem.ControllerConfigSnapshot loadedSnapshot;
|
|
||||||
private long loadedRevision;
|
|
||||||
private SettingsFormState loadedFormState;
|
|
||||||
private KLALBProxySystem.ControllerConfigSnapshot pendingExternalSnapshot;
|
|
||||||
private long pendingExternalRevision;
|
|
||||||
private boolean configSystemClosed;
|
|
||||||
private long bindingGeneration;
|
|
||||||
private Consumer<KLALBProxySystem.ConfigChangeEvent> boundConfigChangeListener;
|
|
||||||
|
|
||||||
private static final class SettingsFormState {
|
|
||||||
private final String language, deviceName, deviceDescription, address, dns, extraRoutes;
|
|
||||||
private final String asn, tunName, webListen, tcpListen, udpListen, openLines, connectLines, ntp;
|
|
||||||
private final String performance, congestion;
|
|
||||||
private final boolean enableTun, webApi, nogui, denyQuery, denyBroadcast;
|
|
||||||
private final List<String> interfaces;
|
|
||||||
private final int connections, burst, upper, lower, nagle, linkNagle;
|
|
||||||
|
|
||||||
private SettingsFormState(KLALBStateGUI3 gui) {
|
|
||||||
Language languageItem = (Language) gui.comboLang.getSelectedItem();
|
|
||||||
language = languageItem == null ? null : languageItem.name();
|
|
||||||
deviceName = gui.deviceNameSet.getText();
|
|
||||||
deviceDescription = gui.deviceDescriptionSet.getText();
|
|
||||||
address = gui.addressFieldSet.getText();
|
|
||||||
dns = gui.dnsAreaSet.getText();
|
|
||||||
extraRoutes = gui.extraRoutesSet.getText();
|
|
||||||
asn = gui.asnFieldSet.getText();
|
|
||||||
tunName = gui.tunDeviceName.getText();
|
|
||||||
webListen = gui.webListenSet.getText();
|
|
||||||
tcpListen = gui.tcpListeningSet.getText();
|
|
||||||
udpListen = gui.udpListeningSet.getText();
|
|
||||||
openLines = gui.openLineTabelSet.getText();
|
|
||||||
connectLines = gui.connectLineTabelSet.getText();
|
|
||||||
ntp = gui.ntpServerSet.getText();
|
|
||||||
PerformanceStrategyItem performanceItem = (PerformanceStrategyItem) gui.comboPerformance.getSelectedItem();
|
|
||||||
performance = performanceItem == null ? null : performanceItem.getStrategy().toString();
|
|
||||||
congestion = String.valueOf(gui.congestions.getComboBox().getSelectedItem());
|
|
||||||
enableTun = gui.enableTUN.isSelected();
|
|
||||||
webApi = gui.webApiEnabled.isSelected();
|
|
||||||
nogui = gui.nogui.isSelected();
|
|
||||||
denyQuery = gui.denyQuery.isSelected();
|
|
||||||
denyBroadcast = gui.denyBroadcast.isSelected();
|
|
||||||
interfaces = new ArrayList<>();
|
|
||||||
for (int i = 0; i < gui.nilsimdl.getSize(); i++) interfaces.add(gui.nilsimdl.getElementAt(i).getName());
|
|
||||||
connections = gui.linkConnectionsCount.getSlider().getValue();
|
|
||||||
burst = gui.burstLimit.getSlider().getValue();
|
|
||||||
upper = gui.delayHbound.getSlider().getValue();
|
|
||||||
lower = gui.delayLbound.getSlider().getValue();
|
|
||||||
nagle = gui.nagleDelayTime.getSlider().getValue();
|
|
||||||
linkNagle = gui.linkNagleDelayTime.getSlider().getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override public boolean equals(Object obj) {
|
|
||||||
if (!(obj instanceof SettingsFormState)) return false;
|
|
||||||
SettingsFormState o = (SettingsFormState) obj;
|
|
||||||
return enableTun == o.enableTun && webApi == o.webApi && nogui == o.nogui
|
|
||||||
&& denyQuery == o.denyQuery && denyBroadcast == o.denyBroadcast
|
|
||||||
&& connections == o.connections && burst == o.burst && upper == o.upper
|
|
||||||
&& lower == o.lower && nagle == o.nagle && linkNagle == o.linkNagle
|
|
||||||
&& Objects.equals(language, o.language) && Objects.equals(deviceName, o.deviceName)
|
|
||||||
&& Objects.equals(deviceDescription, o.deviceDescription) && Objects.equals(address, o.address)
|
|
||||||
&& Objects.equals(dns, o.dns) && Objects.equals(extraRoutes, o.extraRoutes)
|
|
||||||
&& Objects.equals(asn, o.asn) && Objects.equals(tunName, o.tunName)
|
|
||||||
&& Objects.equals(webListen, o.webListen) && Objects.equals(tcpListen, o.tcpListen)
|
|
||||||
&& Objects.equals(udpListen, o.udpListen) && Objects.equals(openLines, o.openLines)
|
|
||||||
&& Objects.equals(connectLines, o.connectLines) && Objects.equals(ntp, o.ntp)
|
|
||||||
&& Objects.equals(performance, o.performance) && Objects.equals(congestion, o.congestion)
|
|
||||||
&& Objects.equals(interfaces, o.interfaces);
|
|
||||||
}
|
|
||||||
@Override public int hashCode() { return Objects.hash(language, deviceName, deviceDescription, address, dns,
|
|
||||||
extraRoutes, asn, tunName, webListen, tcpListen, udpListen, openLines, connectLines, ntp,
|
|
||||||
performance, congestion, enableTun, webApi, nogui, denyQuery, denyBroadcast, interfaces,
|
|
||||||
connections, burst, upper, lower, nagle, linkNagle); }
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 尺寸常量 ====================
|
// ==================== 尺寸常量 ====================
|
||||||
private Dimension dashSize = new Dimension((int) (145 * 0.7), (int) (165 * 0.7)); // 仪表盘尺寸
|
private Dimension dashSize = new Dimension((int) (145 * 0.7), (int) (165 * 0.7)); // 仪表盘尺寸
|
||||||
@@ -1130,9 +1056,14 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
* 保存配置到文件
|
* 保存配置到文件
|
||||||
*/
|
*/
|
||||||
private void saveConfig() {
|
private void saveConfig() {
|
||||||
if (configSystem == null || loadedSnapshot == null) return;
|
if (config == null) {
|
||||||
KLALBControllerConfigItem kck = configSystem.parseControllerConfigCandidate(loadedSnapshot);
|
config = new KLALBConfig();
|
||||||
if (kck == null) return;
|
config.add(new KLALBControllerConfigItem());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (KLALBConfigItem item : config) {
|
||||||
|
if (item instanceof KLALBControllerConfigItem) {
|
||||||
|
KLALBControllerConfigItem kck = (KLALBControllerConfigItem) item;
|
||||||
String oldDeviceName = kck.getDeviceName();
|
String oldDeviceName = kck.getDeviceName();
|
||||||
String oldDeviceDescription = kck.getDeviceDescription();
|
String oldDeviceDescription = kck.getDeviceDescription();
|
||||||
List<MultiProtocolSocketAddress> oldExternalEndpoints = kck.getExternalEndpoints() == null
|
List<MultiProtocolSocketAddress> oldExternalEndpoints = kck.getExternalEndpoints() == null
|
||||||
@@ -1383,30 +1314,28 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
|
|
||||||
kck.setLinkNagleDelayTime(linkNagleDelayTime.getSlider().getValue()*100000L);
|
kck.setLinkNagleDelayTime(linkNagleDelayTime.getSlider().getValue()*100000L);
|
||||||
|
|
||||||
|
boolean deviceNameChanged = !Objects.equals(oldDeviceName, newDeviceName);
|
||||||
|
boolean deviceDescriptionChanged = !Objects.equals(oldDeviceDescription, newDeviceDescription);
|
||||||
|
boolean externalEndpointsChanged = !Objects.equals(oldExternalEndpoints, newExternalEndpoints);
|
||||||
|
boolean extraRoutesChanged = !Objects.equals(oldExtraRoutes, newExtraRoutes);
|
||||||
|
if (deviceNameChanged || deviceDescriptionChanged || externalEndpointsChanged || extraRoutesChanged) {
|
||||||
|
if (kcontroller != null) {
|
||||||
|
kcontroller.publishNodeInfo(newDeviceName, newDeviceDescription, newExternalEndpoints,
|
||||||
|
newExtraRoutes);
|
||||||
|
} else {
|
||||||
kck.setDeviceName(newDeviceName);
|
kck.setDeviceName(newDeviceName);
|
||||||
kck.setDeviceDescription(newDeviceDescription);
|
kck.setDeviceDescription(newDeviceDescription);
|
||||||
kck.setExternalEndpoints(newExternalEndpoints);
|
kck.setExternalEndpoints(newExternalEndpoints);
|
||||||
kck.setExtraRoutes(newExtraRoutes);
|
kck.setExtraRoutes(newExtraRoutes);
|
||||||
try {
|
|
||||||
KLALBProxySystem.CommitResult result = configSystem.commitControllerConfig(loadedRevision, kck,
|
|
||||||
KLALBProxySystem.ConfigChangeSource.SWING);
|
|
||||||
if (!result.isSuccess()) {
|
|
||||||
resolveConfigConflict(result.getSnapshot(), "configsaveconflict");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
loadedSnapshot = result.getSnapshot();
|
}
|
||||||
loadedRevision = result.getRevision();
|
}
|
||||||
loadedFormState = new SettingsFormState(this);
|
}
|
||||||
pendingExternalSnapshot = null;
|
|
||||||
|
// 调用保存回调
|
||||||
|
if (saveComsumer != null) {
|
||||||
|
saveComsumer.accept(config);
|
||||||
JOptionPane.showMessageDialog(this, UIEnv.getRsb().getString("saveconfigsuccess"));
|
JOptionPane.showMessageDialog(this, UIEnv.getRsb().getString("saveconfigsuccess"));
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
JOptionPane.showMessageDialog(this, UIEnv.getRsb().getString("configsavefailed"),
|
|
||||||
UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
|
|
||||||
} catch (RuntimeException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
JOptionPane.showMessageDialog(this, UIEnv.getRsb().getString("configsavefailed"),
|
|
||||||
UIEnv.getRsb().getString("warning"), JOptionPane.WARNING_MESSAGE);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1636,7 +1565,11 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
/**
|
/**
|
||||||
* 加载配置文件
|
* 加载配置文件
|
||||||
*/
|
*/
|
||||||
private void loadConfigCandidate(KLALBControllerConfigItem kck) {
|
public void loadConfig(KLALBConfig config) {
|
||||||
|
this.config = config;
|
||||||
|
for (KLALBConfigItem item : config) {
|
||||||
|
if (item instanceof KLALBControllerConfigItem) {
|
||||||
|
KLALBControllerConfigItem kck = (KLALBControllerConfigItem) item;
|
||||||
|
|
||||||
// 加载语言设置
|
// 加载语言设置
|
||||||
String lg = kck.getLanguage();
|
String lg = kck.getLanguage();
|
||||||
@@ -1763,91 +1696,8 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
long delr=kck.getLinkNagleDelayTime();
|
long delr=kck.getLinkNagleDelayTime();
|
||||||
linkNagleDelayTime.getSlider().setValue((int)(delr/100000L));
|
linkNagleDelayTime.getSlider().setValue((int)(delr/100000L));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loadConfig(KLALBConfig config) {
|
|
||||||
if (configSystem != null) return;
|
|
||||||
this.config = config;
|
|
||||||
if (config == null) return;
|
|
||||||
for (KLALBConfigItem item : config) {
|
|
||||||
if (item instanceof KLALBControllerConfigItem) {
|
|
||||||
loadConfigCandidate((KLALBControllerConfigItem) item);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void bindConfigSystem(KLALBProxySystem system) {
|
|
||||||
if (configSystemClosed || system == null) return;
|
|
||||||
final long generation = ++bindingGeneration;
|
|
||||||
Runnable bind = () -> {
|
|
||||||
if (configSystemClosed || generation != bindingGeneration) return;
|
|
||||||
if (configSystem != null && boundConfigChangeListener != null)
|
|
||||||
configSystem.removeConfigChangeListener(boundConfigChangeListener);
|
|
||||||
configSystem = system;
|
|
||||||
final Consumer<KLALBProxySystem.ConfigChangeEvent> listener = event ->
|
|
||||||
SwingUtilities.invokeLater(() -> handleConfigChange(system, generation, event));
|
|
||||||
boundConfigChangeListener = listener;
|
|
||||||
pendingExternalSnapshot = null;
|
|
||||||
pendingExternalRevision = 0L;
|
|
||||||
loadedSnapshot = null;
|
|
||||||
loadedRevision = 0L;
|
|
||||||
loadedFormState = null;
|
|
||||||
system.addConfigChangeListener(listener);
|
|
||||||
loadedSnapshot = system.getControllerConfigSnapshot();
|
|
||||||
KLALBControllerConfigItem candidate = system.parseControllerConfigCandidate(loadedSnapshot);
|
|
||||||
if (candidate != null) {
|
|
||||||
loadConfigCandidate(candidate);
|
|
||||||
loadedRevision = loadedSnapshot.getRevision();
|
|
||||||
loadedFormState = new SettingsFormState(this);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
if (SwingUtilities.isEventDispatchThread()) bind.run();
|
|
||||||
else SwingUtilities.invokeLater(bind);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void handleConfigChange(KLALBProxySystem sourceSystem, long generation,
|
|
||||||
KLALBProxySystem.ConfigChangeEvent event) {
|
|
||||||
if (configSystemClosed || generation != bindingGeneration || sourceSystem != configSystem
|
|
||||||
|| event.getSource() == KLALBProxySystem.ConfigChangeSource.SWING) return;
|
|
||||||
KLALBProxySystem.ControllerConfigSnapshot snapshot = event.getSnapshot();
|
|
||||||
if (snapshot == null || snapshot.getRevision() <= Math.max(loadedRevision, pendingExternalRevision)) return;
|
|
||||||
if (loadedFormState != null && loadedFormState.equals(new SettingsFormState(this))) {
|
|
||||||
applyExternalSnapshot(snapshot);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (pendingExternalSnapshot == null || snapshot.getRevision() > pendingExternalRevision) {
|
|
||||||
boolean hadPending = pendingExternalSnapshot != null;
|
|
||||||
pendingExternalSnapshot = snapshot;
|
|
||||||
pendingExternalRevision = snapshot.getRevision();
|
|
||||||
if (!hadPending) resolveConfigConflict(snapshot, "configexternalupdate");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void resolveConfigConflict(KLALBProxySystem.ControllerConfigSnapshot snapshot, String messageKey) {
|
|
||||||
if (snapshot != null && snapshot.getRevision() > Math.max(loadedRevision, pendingExternalRevision)) {
|
|
||||||
pendingExternalSnapshot = snapshot;
|
|
||||||
pendingExternalRevision = snapshot.getRevision();
|
|
||||||
}
|
|
||||||
Object[] options = { UIEnv.getRsb().getString("configreload"), UIEnv.getRsb().getString("configcontinue") };
|
|
||||||
int choice = JOptionPane.showOptionDialog(this, UIEnv.getRsb().getString(messageKey),
|
|
||||||
UIEnv.getRsb().getString("configconflicttitle"), JOptionPane.DEFAULT_OPTION,
|
|
||||||
JOptionPane.WARNING_MESSAGE, null, options, options[0]);
|
|
||||||
if (choice == 0 && pendingExternalSnapshot != null
|
|
||||||
&& pendingExternalSnapshot.getRevision() >= loadedRevision) {
|
|
||||||
applyExternalSnapshot(pendingExternalSnapshot);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void applyExternalSnapshot(KLALBProxySystem.ControllerConfigSnapshot snapshot) {
|
|
||||||
KLALBControllerConfigItem candidate = configSystem.parseControllerConfigCandidate(snapshot);
|
|
||||||
if (candidate == null) return;
|
|
||||||
loadConfigCandidate(candidate);
|
|
||||||
loadedSnapshot = snapshot;
|
|
||||||
loadedRevision = snapshot.getRevision();
|
|
||||||
loadedFormState = new SettingsFormState(this);
|
|
||||||
pendingExternalSnapshot = null;
|
|
||||||
pendingExternalRevision = 0L;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ==================== 辅助方法 ====================
|
// ==================== 辅助方法 ====================
|
||||||
/**
|
/**
|
||||||
@@ -1923,7 +1773,6 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
* 设置保存配置的回调函数
|
* 设置保存配置的回调函数
|
||||||
*/
|
*/
|
||||||
public void setSaveComsumer(Consumer<KLALBConfig> saveComsumer) {
|
public void setSaveComsumer(Consumer<KLALBConfig> saveComsumer) {
|
||||||
if (configSystem != null) return;
|
|
||||||
this.saveComsumer = saveComsumer;
|
this.saveComsumer = saveComsumer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1939,11 +1788,6 @@ public class KLALBStateGUI3 extends XFrame {
|
|||||||
* 关闭窗口并清理资源
|
* 关闭窗口并清理资源
|
||||||
*/
|
*/
|
||||||
public void close() {
|
public void close() {
|
||||||
bindingGeneration++;
|
|
||||||
configSystemClosed = true;
|
|
||||||
if (configSystem != null && boundConfigChangeListener != null)
|
|
||||||
configSystem.removeConfigChangeListener(boundConfigChangeListener);
|
|
||||||
boundConfigChangeListener = null;
|
|
||||||
for (int i = 0; i < tabbedPane.getTabCount(); i++) {
|
for (int i = 0; i < tabbedPane.getTabCount(); i++) {
|
||||||
Component component = tabbedPane.getComponentAt(i);
|
Component component = tabbedPane.getComponentAt(i);
|
||||||
if (component instanceof NodeInformationPanel) {
|
if (component instanceof NodeInformationPanel) {
|
||||||
|
|||||||
@@ -863,11 +863,17 @@ public class KLALBWebServer {
|
|||||||
String body = readRequestBody(exchange);
|
String body = readRequestBody(exchange);
|
||||||
try {
|
try {
|
||||||
JsonObject json = new JsonParser().parse(body).getAsJsonObject();
|
JsonObject json = new JsonParser().parse(body).getAsJsonObject();
|
||||||
KLALBProxySystem.ControllerConfigSnapshot baseSnapshot = proxySystem.getControllerConfigSnapshot();
|
KLALBControllerConfigItem current = proxySystem.getControllerConfig();
|
||||||
KLALBControllerConfigItem current = proxySystem.parseControllerConfigCandidate(baseSnapshot);
|
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
String newDeviceName = current.getDeviceName();
|
String oldDeviceName = current.getDeviceName();
|
||||||
String newDeviceDescription = current.getDeviceDescription();
|
String oldDeviceDescription = current.getDeviceDescription();
|
||||||
|
List<MultiProtocolSocketAddress> oldExternalEndpoints = current.getExternalEndpoints() == null
|
||||||
|
? null
|
||||||
|
: new ArrayList<MultiProtocolSocketAddress>(current.getExternalEndpoints());
|
||||||
|
List<String> oldExtraRoutes = current.getExtraRoutes() == null
|
||||||
|
? null : new ArrayList<String>(current.getExtraRoutes());
|
||||||
|
String newDeviceName = oldDeviceName;
|
||||||
|
String newDeviceDescription = oldDeviceDescription;
|
||||||
List<MultiProtocolSocketAddress> newExternalEndpoints = current.getExternalEndpoints();
|
List<MultiProtocolSocketAddress> newExternalEndpoints = current.getExternalEndpoints();
|
||||||
List<String> newExtraRoutes = current.getExtraRoutes();
|
List<String> newExtraRoutes = current.getExtraRoutes();
|
||||||
if (json.has("deviceName") && !json.get("deviceName").isJsonNull()) {
|
if (json.has("deviceName") && !json.get("deviceName").isJsonNull()) {
|
||||||
@@ -1066,32 +1072,37 @@ public class KLALBWebServer {
|
|||||||
current.setDenyExternalEndpointBroadcast(json.get("denyLineTableBroadcast").getAsBoolean());
|
current.setDenyExternalEndpointBroadcast(json.get("denyLineTableBroadcast").getAsBoolean());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean deviceNameChanged = !Objects.equals(oldDeviceName, newDeviceName);
|
||||||
|
boolean deviceDescriptionChanged = !Objects.equals(oldDeviceDescription, newDeviceDescription);
|
||||||
|
boolean externalEndpointsChanged = !Objects.equals(oldExternalEndpoints, newExternalEndpoints);
|
||||||
|
boolean extraRoutesChanged = !Objects.equals(oldExtraRoutes, newExtraRoutes);
|
||||||
|
if (deviceNameChanged || deviceDescriptionChanged || externalEndpointsChanged || extraRoutesChanged) {
|
||||||
|
KLALBController kc = proxySystem.getKlalbController();
|
||||||
|
if (kc != null) {
|
||||||
|
kc.publishNodeInfo(newDeviceName, newDeviceDescription, newExternalEndpoints,
|
||||||
|
newExtraRoutes);
|
||||||
|
} else {
|
||||||
current.setDeviceName(newDeviceName);
|
current.setDeviceName(newDeviceName);
|
||||||
current.setDeviceDescription(newDeviceDescription);
|
current.setDeviceDescription(newDeviceDescription);
|
||||||
current.setExternalEndpoints(newExternalEndpoints);
|
current.setExternalEndpoints(newExternalEndpoints);
|
||||||
current.setExtraRoutes(newExtraRoutes);
|
current.setExtraRoutes(newExtraRoutes);
|
||||||
KLALBProxySystem.CommitResult commitResult = proxySystem.commitControllerConfig(
|
}
|
||||||
baseSnapshot.getRevision(), current,
|
}
|
||||||
KLALBProxySystem.ConfigChangeSource.WEB);
|
|
||||||
if (!commitResult.isSuccess()) {
|
// Trigger GUI save consumer or save directly
|
||||||
JsonObject conflict = new JsonObject();
|
if (proxySystem.getKLALBGUI() != null && proxySystem.getKLALBGUI().getSaveComsumer() != null) {
|
||||||
conflict.addProperty("success", false);
|
proxySystem.getKLALBGUI().getSaveComsumer().accept(proxySystem.getConfig());
|
||||||
conflict.addProperty("revision", commitResult.getRevision());
|
} else {
|
||||||
conflict.addProperty("error", "Configuration revision conflict");
|
proxySystem.saveConfigToFile();
|
||||||
sendJsonResponse(exchange, 409, conflict);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JsonObject resp = new JsonObject();
|
JsonObject resp = new JsonObject();
|
||||||
resp.addProperty("success", true);
|
resp.addProperty("success", true);
|
||||||
resp.addProperty("revision", commitResult.getRevision());
|
|
||||||
resp.addProperty("message", "Configuration updated successfully");
|
resp.addProperty("message", "Configuration updated successfully");
|
||||||
sendJsonResponse(exchange, 200, resp);
|
sendJsonResponse(exchange, 200, resp);
|
||||||
} else {
|
} else {
|
||||||
sendError(exchange, 500, "Current configuration is null");
|
sendError(exchange, 500, "Current configuration is null");
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
|
||||||
sendError(exchange, 500, "Failed to persist configuration: " + e.getMessage());
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
sendError(exchange, 400, "Failed to update configuration: " + e.getMessage());
|
sendError(exchange, 400, "Failed to update configuration: " + e.getMessage());
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user