Rework service store handling

This commit is contained in:
crschnick
2025-10-21 16:44:54 +00:00
parent c3c415bb5a
commit 916b6a3779
6 changed files with 77 additions and 54 deletions
@@ -10,6 +10,7 @@ import io.xpipe.app.util.HostHelper;
import io.xpipe.app.util.LicenseProvider;
import io.xpipe.app.util.Validators;
import io.xpipe.ext.base.host.HostAddressStore;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@@ -21,36 +22,6 @@ import lombok.experimental.SuperBuilder;
@ToString
public abstract class AbstractServiceStore implements SingletonSessionStore<NetworkTunnelSession>, DataStore {
public static boolean requiresTunnel(NetworkTunnelStore t) {
if (!t.isLocallyTunnelable()) {
var parent = t.getNetworkParent();
if (!(parent instanceof NetworkTunnelStore nts)) {
return false;
}
return nts.requiresTunnel();
}
return t.requiresTunnel();
}
public static boolean requiresManualAddress(DataStore s) {
if (!(s instanceof NetworkTunnelStore t)) {
return true;
}
if (!t.isLocallyTunnelable()) {
var parent = t.getNetworkParent();
if (!(parent instanceof NetworkTunnelStore nts)) {
return false;
}
return nts.requiresTunnel();
}
return t.requiresTunnel();
}
private final Integer remotePort;
private final Integer localPort;
private final ServiceProtocolType serviceProtocolType;
@@ -81,6 +52,15 @@ public abstract class AbstractServiceStore implements SingletonSessionStore<Netw
}
public boolean requiresTunnel() {
if (getAddress() != null) {
var gateway = getGateway();
if (gateway != null) {
return gateway.getStore().requiresTunnel();
} else {
return false;
}
}
if (getHost() == null || !(getHost().getStore() instanceof NetworkTunnelStore t)) {
return false;
}
@@ -92,15 +72,30 @@ public abstract class AbstractServiceStore implements SingletonSessionStore<Netw
}
return nts.requiresTunnel();
} else {
return t.requiresTunnel();
}
return t.requiresTunnel();
}
@Override
public NetworkTunnelSession newSession() {
if (!(getHost().getStore() instanceof NetworkTunnelStore t)) {
return null;
if (getAddress() != null) {
if (getGateway() == null || !getGateway().getStore().isLocallyTunnelable()) {
return null;
}
}
if (getHost() != null) {
if (!(getHost().getStore() instanceof NetworkTunnelStore t)) {
return null;
}
if (!t.isLocallyTunnelable()) {
var parent = t.getNetworkParent();
if (!(parent instanceof NetworkTunnelStore)) {
return null;
}
}
}
var f = LicenseProvider.get().getFeature("services");
@@ -118,10 +113,16 @@ public abstract class AbstractServiceStore implements SingletonSessionStore<Netw
var l = localPort != null ? localPort : HostHelper.findRandomOpenPortOnAllLocalInterfaces();
if (getAddress() != null) {
var gateway = getGateway();
return gateway.getStore().createTunnelSession(l, remotePort, getAddress());
}
var t = (NetworkTunnelStore) getHost().getStore();
var parent = t.getNetworkParent();
if (!t.isLocallyTunnelable() && parent instanceof NetworkTunnelStore nts) {
return nts.createTunnelSession(
l, remotePort, nts.getTunnelHostName() != null ? nts.getTunnelHostName() : "localhost");
l, remotePort, t.getTunnelHostName() != null ? t.getTunnelHostName() : "localhost");
}
return t.createTunnelSession(l, remotePort, "localhost");
@@ -10,9 +10,11 @@ import io.xpipe.app.util.DocumentationLink;
import io.xpipe.app.util.StoreStateFormat;
import io.xpipe.core.FailableRunnable;
import io.xpipe.ext.base.host.AbstractHostStore;
import javafx.beans.binding.Bindings;
import javafx.beans.value.ObservableValue;
import java.util.ArrayList;
import java.util.List;
public abstract class AbstractServiceStoreProvider implements SingletonSessionStoreProvider, DataStoreProvider {
@@ -30,20 +32,38 @@ public abstract class AbstractServiceStoreProvider implements SingletonSessionSt
@Override
public boolean supportsSession(SingletonSessionStore<?> s) {
var abs = (AbstractServiceStore) s;
if (abs.getHost() != null && (!(abs.getHost().getStore() instanceof NetworkTunnelStore t)
|| !t.requiresTunnel()
|| !t.isLocallyTunnelable())) {
return false;
if (abs.getAddress() != null) {
return abs.getGateway() != null && abs.getGateway().getStore().isLocallyTunnelable() && abs.getGateway().getStore().requiresTunnel();
}
if (abs.getHost() == null && (abs.getGateway() == null ||
!abs.getGateway().getStore().isLocallyTunnelable() || !abs.getGateway().getStore().requiresTunnel())) {
return false;
if (abs.getHost() != null) {
if (abs.getHost().getStore() instanceof AbstractHostStore a) {
return a.getGateway() != null && a.getGateway().getStore().requiresTunnel() && a.getGateway().getStore().isLocallyTunnelable();
}
if (abs.getHost().getStore() instanceof NetworkTunnelStore t) {
if (!t.requiresTunnel()) {
return false;
}
if (t.isLocallyTunnelable()) {
return true;
}
var parent = t.getNetworkParent();
if (!t.isLocallyTunnelable() && parent instanceof NetworkTunnelStore nts) {
return nts.isLocallyTunnelable();
}
return false;
}
}
return true;
return false;
}
@Override
public FailableRunnable<Exception> launch(DataStoreEntry store) {
return () -> {
@@ -62,9 +82,15 @@ public abstract class AbstractServiceStoreProvider implements SingletonSessionSt
@Override
public List<String> getSearchableTerms(DataStore store) {
AbstractServiceStore s = store.asNeeded();
return s.getLocalPort() != null
? List.of("" + s.getRemotePort(), "" + s.getLocalPort())
: List.of("" + s.getRemotePort());
var l = new ArrayList<String>();
l.add("" + s.getRemotePort());
if (s.getLocalPort() != null) {
l.add("" + s.getLocalPort());
}
if (s.getAddress() != null) {
l.add(s.getAddress());
}
return l;
}
@Override
@@ -109,11 +135,6 @@ public abstract class AbstractServiceStoreProvider implements SingletonSessionSt
return "base:service_icon.svg";
}
@Override
public boolean showToggleWhenInactive(SingletonSessionStore<?> store) {
return false;
}
@Override
public Comp<?> stateDisplay(StoreEntryWrapper w) {
return new SystemStateComp(Bindings.createObjectBinding(
@@ -22,7 +22,7 @@ import lombok.extern.jackson.Jacksonized;
@ToString(callSuper = true)
public final class CustomServiceStore extends AbstractServiceStore implements AbstractHostTransformStore {
private final DataStoreEntryRef<HostAddressStore> host;
private final DataStoreEntryRef<DataStore> host;
private final String address;
private final DataStoreEntryRef<NetworkTunnelStore> gateway;
@@ -69,7 +69,7 @@ public class CustomServiceStoreProvider extends AbstractServiceStoreProvider {
var serviceProtocolType = new SimpleObjectProperty<>(st.getServiceProtocolType());
var hostChoice = new StoreComboChoiceComp<>(
hostStore -> hostStore.getHostAddress().get(),
hostStore -> hostStore instanceof AbstractHostStore a ? a.getHostAddress().get() : hostStore instanceof NetworkTunnelStore t ? t.getTunnelHostName() : "?",
entry,
comboHost,
NetworkTunnelStore.class,
@@ -7,6 +7,7 @@ import io.xpipe.app.storage.DataStoreEntryRef;
import io.xpipe.app.util.Validators;
import com.fasterxml.jackson.annotation.JsonTypeName;
import io.xpipe.ext.base.host.HostAddressStore;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
+1 -1
View File
@@ -1668,7 +1668,7 @@ abstractHostAddress=Host address
abstractHostAddressDescription=The address of the host
abstractHostGateway=Gateway
abstractHostGatewayDescription=The optional gateway system through which to reach this host
abstractHostConvert=Convert to abstract host
abstractHostConvert=Convert to abstract host entry
abstractHostNoConnections=No available connections
abstractHostHasConnections=$COUNT$ available connections
abstractHostHasConnection=$COUNT$ available connection