WIP: auto resolver

This commit is contained in:
kirillius 2026-05-17 13:40:33 +03:00
parent c0d5fb5d1f
commit c1dbaa5bfc
4 changed files with 68 additions and 11 deletions

View File

@ -34,6 +34,11 @@ public class NetworkResourceBundle {
@JSONArrayProperty(type = String.class) @JSONArrayProperty(type = String.class)
private List<String> domains = new ArrayList<>(); private List<String> domains = new ArrayList<>();
@Getter
@Setter
@JSONProperty(required = false)
private boolean resolveDomains = false;
@Override @Override
public boolean equals(Object o) { public boolean equals(Object o) {
if (!(o instanceof NetworkResourceBundle that)) return false; if (!(o instanceof NetworkResourceBundle that)) return false;

View File

@ -38,8 +38,7 @@ public class NetworkingService extends AppService {
private final NetworkResourceBundle inputResources = new NetworkResourceBundle(); private final NetworkResourceBundle inputResources = new NetworkResourceBundle();
@Getter @Getter
private final NetworkResourceBundle outputResources = new NetworkResourceBundle(); private final NetworkResourceBundle outputResources = new NetworkResourceBundle();
@Getter
private final List<String> autoResolveDomains = new ArrayList<>();
private final Map<Integer, List<IPv4Subnet>> prefixCache = new ConcurrentHashMap<>(); private final Map<Integer, List<IPv4Subnet>> prefixCache = new ConcurrentHashMap<>();
private final Map<String, ResolverCacheEntry> domainCache = new ConcurrentHashMap<>(); private final Map<String, ResolverCacheEntry> domainCache = new ConcurrentHashMap<>();
@ -84,6 +83,33 @@ public class NetworkingService extends AppService {
SystemLogger.error("Failed to load domain cache file " + asCacheFile.getPath(), CTX, e); SystemLogger.error("Failed to load domain cache file " + asCacheFile.getPath(), CTX, e);
} }
} }
executor.execute(this::autoResolverWorker);
}
private void autoResolverWorker() {
var current = new HashSet<IPv4Subnet>();
domainCache.forEach((host, entry) -> current.addAll(entry.getAddresses().keySet()));
resolveDomains(List.copyOf(context.getServiceManager().getService(SubscriptionService.class).getAutoResolvingDomains()));
var resolved = new HashSet<IPv4Subnet>();
domainCache.forEach((host, entry) -> resolved.addAll(entry.getAddresses().keySet()));
if (resolved.size() != current.size()) {
rebuildInputs();
} else {
var updated = false;
for (var subnet : resolved) {
if (!current.contains(subnet)) {
updated = true;
break;
}
}
if (updated) {
rebuildInputs();
}
}
} }
private void rebuildInputs() { private void rebuildInputs() {
@ -154,7 +180,7 @@ public class NetworkingService extends AppService {
} }
} }
resolveDomains(autoResolveDomains); resolveDomains(List.copyOf(context.getServiceManager().getService(SubscriptionService.class).getAutoResolvingDomains()));
if (config.isCachingDomains()) { if (config.isCachingDomains()) {
try (var os = new FileOutputStream(domainCacheFile)) { try (var os = new FileOutputStream(domainCacheFile)) {

View File

@ -8,11 +8,9 @@ import ru.kirillius.utils.logging.SystemLogger;
import java.io.IOException; import java.io.IOException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
/** /**
@ -21,14 +19,14 @@ import java.util.concurrent.atomic.AtomicReference;
public class SubscriptionService extends AppService { public class SubscriptionService extends AppService {
private final ExecutorService executor = Executors.newSingleThreadExecutor(); private final ExecutorService executor = Executors.newSingleThreadExecutor();
private final Map<Class<? extends SubscriptionProvider>, SubscriptionProvider> providerCache = new ConcurrentHashMap<>(); private final Map<Class<? extends SubscriptionProvider>, SubscriptionProvider> providerCache = new ConcurrentHashMap<>();
private final AtomicReference<Future<?>> updateProcess = new AtomicReference<>(); private final AtomicReference<Future<?>> updateProcess = new AtomicReference<>();
@Getter @Getter
private final NetworkResourceBundle outputResources = new NetworkResourceBundle(); private final NetworkResourceBundle outputResources = new NetworkResourceBundle();
@Getter
private final List<String> autoResolvingDomains = new CopyOnWriteArrayList<>();
public SubscriptionService(Context context) { public SubscriptionService(Context context) {
super(context); super(context);
@ -45,7 +43,6 @@ public class SubscriptionService extends AppService {
@Getter @Getter
private final Map<String, NetworkResourceBundle> availableResources = new ConcurrentHashMap<>(); private final Map<String, NetworkResourceBundle> availableResources = new ConcurrentHashMap<>();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private <T extends SubscriptionProvider> T getProvider(Class<T> providerType) { private <T extends SubscriptionProvider> T getProvider(Class<T> providerType) {
if (!providerCache.containsKey(providerType)) { if (!providerCache.containsKey(providerType)) {
@ -62,6 +59,9 @@ public class SubscriptionService extends AppService {
return; return;
} }
updateProcess.set(executor.submit(() -> { updateProcess.set(executor.submit(() -> {
var available = new HashMap<String, NetworkResourceBundle>(); var available = new HashMap<String, NetworkResourceBundle>();
var bundle = new NetworkResourceBundle(); var bundle = new NetworkResourceBundle();
@ -90,6 +90,12 @@ public class SubscriptionService extends AppService {
availableResources.putAll(available); availableResources.putAll(available);
outputResources.clear(); outputResources.clear();
outputResources.add(bundle); outputResources.add(bundle);
available.values().forEach(b -> {
if (b.isResolveDomains()) {
autoResolvingDomains.addAll(b.getDomains());
}
});
try { try {
context.getEventsHandler().getSubscriptionsUpdateEvent().invoke(outputResources); context.getEventsHandler().getSubscriptionsUpdateEvent().invoke(outputResources);
} catch (Exception e) { } catch (Exception e) {
@ -100,7 +106,6 @@ public class SubscriptionService extends AppService {
private final static String CTX = SubscriptionService.class.getSimpleName(); private final static String CTX = SubscriptionService.class.getSimpleName();
/** /**
* Shuts down the executor used for update tasks. * Shuts down the executor used for update tasks.
*/ */

View File

@ -31,6 +31,27 @@ class IPv4UtilTest {
//subnets.forEach(System.out::println);
var merged = IPv4Util.summarySubnets(subnets, 51).getResult();
merged.forEach(System.out::println);
assertThat(merged).isNotNull();
}
@Test
void summarySubnetsShishanyaCase() {
var subnets = new ArrayList<IPv4Subnet>();
subnets.add(new IPv4Subnet("8.6.112.0/32"));
subnets.add(new IPv4Subnet("8.6.112.0/24"));
//subnets.forEach(System.out::println); //subnets.forEach(System.out::println);
var merged = IPv4Util.summarySubnets(subnets, 51).getResult(); var merged = IPv4Util.summarySubnets(subnets, 51).getResult();