mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 11:39:11 +03:00
[FEATURE] Updates cache
This commit is contained in:
parent
8445ed2dca
commit
c719f2448e
6 changed files with 136 additions and 41 deletions
|
@ -46,7 +46,6 @@
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The main LaunchServer class. Contains links to all necessary objects
|
* The main LaunchServer class. Contains links to all necessary objects
|
||||||
|
@ -115,6 +114,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab
|
||||||
public final PingServerManager pingServerManager;
|
public final PingServerManager pingServerManager;
|
||||||
public final FeaturesManager featuresManager;
|
public final FeaturesManager featuresManager;
|
||||||
public final KeyAgreementManager keyAgreementManager;
|
public final KeyAgreementManager keyAgreementManager;
|
||||||
|
public final UpdatesManager updatesManager;
|
||||||
// HWID ban + anti-brutforce
|
// HWID ban + anti-brutforce
|
||||||
public final CertificateManager certificateManager;
|
public final CertificateManager certificateManager;
|
||||||
// Server
|
// Server
|
||||||
|
@ -127,6 +127,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab
|
||||||
public final LauncherModuleLoader launcherModuleLoader;
|
public final LauncherModuleLoader launcherModuleLoader;
|
||||||
private final Logger logger = LogManager.getLogger();
|
private final Logger logger = LogManager.getLogger();
|
||||||
public LaunchServerConfig config;
|
public LaunchServerConfig config;
|
||||||
|
@Deprecated
|
||||||
public volatile Map<String, HashedDir> updatesDirMap;
|
public volatile Map<String, HashedDir> updatesDirMap;
|
||||||
// Updates and profiles
|
// Updates and profiles
|
||||||
private volatile Set<ClientProfile> profilesList;
|
private volatile Set<ClientProfile> profilesList;
|
||||||
|
@ -173,6 +174,7 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La
|
||||||
pingServerManager = new PingServerManager(this);
|
pingServerManager = new PingServerManager(this);
|
||||||
featuresManager = new FeaturesManager(this);
|
featuresManager = new FeaturesManager(this);
|
||||||
authManager = new AuthManager(this);
|
authManager = new AuthManager(this);
|
||||||
|
updatesManager = new UpdatesManager(this);
|
||||||
RestoreResponse.registerProviders(this);
|
RestoreResponse.registerProviders(this);
|
||||||
//Generate or set new Certificate API
|
//Generate or set new Certificate API
|
||||||
certificateManager.orgName = config.projectName;
|
certificateManager.orgName = config.projectName;
|
||||||
|
@ -316,10 +318,12 @@ public void setProfiles(Set<ClientProfile> profilesList) {
|
||||||
this.profilesList = Collections.unmodifiableSet(profilesList);
|
this.profilesList = Collections.unmodifiableSet(profilesList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public HashedDir getUpdateDir(String name) {
|
public HashedDir getUpdateDir(String name) {
|
||||||
return updatesDirMap.get(name);
|
return updatesDirMap.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public Set<Entry<String, HashedDir>> getUpdateDirs() {
|
public Set<Entry<String, HashedDir>> getUpdateDirs() {
|
||||||
return updatesDirMap.entrySet();
|
return updatesDirMap.entrySet();
|
||||||
}
|
}
|
||||||
|
@ -349,8 +353,7 @@ public void run() {
|
||||||
try {
|
try {
|
||||||
if (!IOHelper.isDir(updatesDir))
|
if (!IOHelper.isDir(updatesDir))
|
||||||
Files.createDirectory(updatesDir);
|
Files.createDirectory(updatesDir);
|
||||||
syncUpdatesDir(null);
|
updatesManager.readUpdatesDir();
|
||||||
modulesManager.invokeEvent(new LaunchServerUpdatesSyncEvent(this));
|
|
||||||
|
|
||||||
// Sync profiles dir
|
// Sync profiles dir
|
||||||
if (!IOHelper.isDir(profilesDir))
|
if (!IOHelper.isDir(profilesDir))
|
||||||
|
@ -402,37 +405,7 @@ public void syncProfilesDir() throws IOException {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
||||||
logger.info("Syncing updates dir");
|
updatesManager.syncUpdatesDir(dirs);
|
||||||
Map<String, HashedDir> newUpdatesDirMap = new HashMap<>(16);
|
|
||||||
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(updatesDir)) {
|
|
||||||
for (final Path updateDir : dirStream) {
|
|
||||||
if (Files.isHidden(updateDir))
|
|
||||||
continue; // Skip hidden
|
|
||||||
|
|
||||||
// Resolve name and verify is dir
|
|
||||||
String name = IOHelper.getFileName(updateDir);
|
|
||||||
if (!IOHelper.isDir(updateDir)) {
|
|
||||||
if (!IOHelper.isFile(updateDir) && Stream.of(".jar", ".exe", ".hash").noneMatch(e -> updateDir.toString().endsWith(e)))
|
|
||||||
logger.warn("Not update dir: '{}'", name);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add from previous map (it's guaranteed to be non-null)
|
|
||||||
if (dirs != null && !dirs.contains(name)) {
|
|
||||||
HashedDir hdir = updatesDirMap.get(name);
|
|
||||||
if (hdir != null) {
|
|
||||||
newUpdatesDirMap.put(name, hdir);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync and sign update dir
|
|
||||||
logger.info("Syncing '{}' update dir", name);
|
|
||||||
HashedDir updateHDir = new HashedDir(updateDir, null, true, true);
|
|
||||||
newUpdatesDirMap.put(name, updateHDir);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
updatesDirMap = Collections.unmodifiableMap(newUpdatesDirMap);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void restart() {
|
public void restart() {
|
||||||
|
|
|
@ -35,6 +35,7 @@ public final class LaunchServerConfig {
|
||||||
public String[] mirrors;
|
public String[] mirrors;
|
||||||
public String binaryName;
|
public String binaryName;
|
||||||
public boolean copyBinaries = true;
|
public boolean copyBinaries = true;
|
||||||
|
public boolean cacheUpdates = true;
|
||||||
public LauncherConfig.LauncherEnvironment env;
|
public LauncherConfig.LauncherEnvironment env;
|
||||||
public Map<String, AuthProviderPair> auth;
|
public Map<String, AuthProviderPair> auth;
|
||||||
@Deprecated
|
@Deprecated
|
||||||
|
|
|
@ -0,0 +1,125 @@
|
||||||
|
package pro.gravit.launchserver.manangers;
|
||||||
|
|
||||||
|
import org.apache.logging.log4j.LogManager;
|
||||||
|
import org.apache.logging.log4j.Logger;
|
||||||
|
import pro.gravit.launcher.hasher.HashedDir;
|
||||||
|
import pro.gravit.launcher.serialize.HInput;
|
||||||
|
import pro.gravit.launcher.serialize.HOutput;
|
||||||
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.launchserver.modules.events.LaunchServerUpdatesSyncEvent;
|
||||||
|
import pro.gravit.utils.helper.IOHelper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.DirectoryStream;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class UpdatesManager {
|
||||||
|
private final LaunchServer server;
|
||||||
|
private final Logger logger = LogManager.getLogger();
|
||||||
|
private volatile Map<String, HashedDir> updatesDirMap;
|
||||||
|
private Path cacheFile;
|
||||||
|
|
||||||
|
public UpdatesManager(LaunchServer server) {
|
||||||
|
this.server = server;
|
||||||
|
this.cacheFile = server.dir.resolve(".updates-cache");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeCache(Path file) throws IOException {
|
||||||
|
try (HOutput output = new HOutput(IOHelper.newOutput(file))) {
|
||||||
|
output.writeLength(updatesDirMap.size(), 0);
|
||||||
|
for (Map.Entry<String, HashedDir> entry : updatesDirMap.entrySet()) {
|
||||||
|
output.writeString(entry.getKey(), 0);
|
||||||
|
entry.getValue().write(output);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.debug("Saved {} updates to cache", updatesDirMap.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void readCache(Path file) throws IOException {
|
||||||
|
Map<String, HashedDir> updatesDirMap = new HashMap<>(16);
|
||||||
|
try (HInput input = new HInput(IOHelper.newInput(file))) {
|
||||||
|
int size = input.readLength(0);
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
String name = input.readString(0);
|
||||||
|
HashedDir dir = new HashedDir(input);
|
||||||
|
updatesDirMap.put(name, dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.debug("Found {} updates from cache", updatesDirMap.size());
|
||||||
|
this.updatesDirMap = Collections.unmodifiableMap(updatesDirMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readUpdatesDir() throws IOException {
|
||||||
|
if (server.config.cacheUpdates) {
|
||||||
|
if (Files.exists(cacheFile)) {
|
||||||
|
try {
|
||||||
|
readCache(cacheFile);
|
||||||
|
return;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
logger.error("Read updates cache failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
syncUpdatesDir(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
||||||
|
logger.info("Syncing updates dir");
|
||||||
|
Map<String, HashedDir> newUpdatesDirMap = new HashMap<>(16);
|
||||||
|
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(server.updatesDir)) {
|
||||||
|
for (final Path updateDir : dirStream) {
|
||||||
|
if (Files.isHidden(updateDir))
|
||||||
|
continue; // Skip hidden
|
||||||
|
|
||||||
|
// Resolve name and verify is dir
|
||||||
|
String name = IOHelper.getFileName(updateDir);
|
||||||
|
if (!IOHelper.isDir(updateDir)) {
|
||||||
|
if (!IOHelper.isFile(updateDir) && Stream.of(".jar", ".exe", ".hash").noneMatch(e -> updateDir.toString().endsWith(e)))
|
||||||
|
logger.warn("Not update dir: '{}'", name);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add from previous map (it's guaranteed to be non-null)
|
||||||
|
if (dirs != null && !dirs.contains(name)) {
|
||||||
|
HashedDir hdir = updatesDirMap.get(name);
|
||||||
|
if (hdir != null) {
|
||||||
|
newUpdatesDirMap.put(name, hdir);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sync and sign update dir
|
||||||
|
logger.info("Syncing '{}' update dir", name);
|
||||||
|
HashedDir updateHDir = new HashedDir(updateDir, null, true, true);
|
||||||
|
newUpdatesDirMap.put(name, updateHDir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
updatesDirMap = Collections.unmodifiableMap(newUpdatesDirMap);
|
||||||
|
if (server.config.cacheUpdates) {
|
||||||
|
try {
|
||||||
|
writeCache(cacheFile);
|
||||||
|
} catch (Throwable e) {
|
||||||
|
logger.error("Write updates cache failed", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
server.modulesManager.invokeEvent(new LaunchServerUpdatesSyncEvent(server));
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashSet<String> getUpdatesList() {
|
||||||
|
HashSet<String> set = new HashSet<>();
|
||||||
|
for (Map.Entry<String, HashedDir> entry : updatesDirMap.entrySet())
|
||||||
|
set.add(entry.getKey());
|
||||||
|
return set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public HashedDir getUpdate(String name) {
|
||||||
|
return updatesDirMap.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addUpdate(String name, HashedDir dir) {
|
||||||
|
updatesDirMap.put(name, dir);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,12 +2,10 @@
|
||||||
|
|
||||||
import io.netty.channel.ChannelHandlerContext;
|
import io.netty.channel.ChannelHandlerContext;
|
||||||
import pro.gravit.launcher.events.request.UpdateListRequestEvent;
|
import pro.gravit.launcher.events.request.UpdateListRequestEvent;
|
||||||
import pro.gravit.launcher.hasher.HashedDir;
|
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
import pro.gravit.launchserver.socket.response.SimpleResponse;
|
||||||
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
public class UpdateListResponse extends SimpleResponse {
|
public class UpdateListResponse extends SimpleResponse {
|
||||||
|
|
||||||
|
@ -22,9 +20,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
sendError("Access denied");
|
sendError("Access denied");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashSet<String> set = new HashSet<>();
|
HashSet<String> set = server.updatesManager.getUpdatesList();
|
||||||
for (Map.Entry<String, HashedDir> entry : server.updatesDirMap.entrySet())
|
|
||||||
set.add(entry.getKey());
|
|
||||||
sendResult(new UpdateListRequestEvent(set));
|
sendResult(new UpdateListRequestEvent(set));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
||||||
sendError("Invalid request");
|
sendError("Invalid request");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
HashedDir dir = server.updatesDirMap.get(dirName);
|
HashedDir dir = server.updatesManager.getUpdate(dirName);
|
||||||
if (dir == null) {
|
if (dir == null) {
|
||||||
sendError(String.format("Directory %s not found", dirName));
|
sendError(String.format("Directory %s not found", dirName));
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -67,7 +67,7 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
|
||||||
context.javaVersion = version;
|
context.javaVersion = version;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (version.enabledJavaFX) {
|
if (version.enabledJavaFX == context.javaVersion.enabledJavaFX) {
|
||||||
if (context.javaVersion.version < version.version) {
|
if (context.javaVersion.version < version.version) {
|
||||||
context.javaVersion = version;
|
context.javaVersion = version;
|
||||||
} else if (context.javaVersion.version == version.version && context.javaVersion.build < version.build) {
|
} else if (context.javaVersion.version == version.version && context.javaVersion.build < version.build) {
|
||||||
|
|
Loading…
Reference in a new issue