diff --git a/LaunchServer/build.gradle b/LaunchServer/build.gradle index ffe79a90..baadb9cd 100644 --- a/LaunchServer/build.gradle +++ b/LaunchServer/build.gradle @@ -10,6 +10,9 @@ maven { url "https://jcenter.bintray.com/" } + maven { + url "https://jitpack.io/" + } } sourceCompatibility = '17' @@ -72,6 +75,7 @@ task cleanjar(type: Jar, dependsOn: jar) { dependencies { pack project(':LauncherAPI') bundle group: 'me.tongfei', name: 'progressbar', version: '0.9.2' + bundle group: 'com.github.Marcono1234', name: 'gson-record-type-adapter-factory', version: 'v0.1.0' bundle group: 'org.fusesource.jansi', name: 'jansi', version: rootProject['verJansi'] bundle group: 'org.jline', name: 'jline', version: rootProject['verJline'] bundle group: 'org.jline', name: 'jline-reader', version: rootProject['verJline'] diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java index 0c501f62..fe7be0da 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java @@ -3,9 +3,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import pro.gravit.launcher.Launcher; -import pro.gravit.launcher.NeedGarbageCollection; import pro.gravit.launcher.managers.ConfigManager; -import pro.gravit.launcher.managers.GarbageManager; import pro.gravit.launcher.modules.events.ClosePhase; import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launchserver.auth.AuthProviderPair; @@ -104,6 +102,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab public final AuthManager authManager; public final ReconfigurableManager reconfigurableManager; public final ConfigManager configManager; + @Deprecated public final PingServerManager pingServerManager; public final FeaturesManager featuresManager; public final KeyAgreementManager keyAgreementManager; @@ -166,7 +165,6 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La config.init(ReloadType.FULL); registerObject("launchServer", this); - GarbageManager.registerNeedGC(sessionManager); pro.gravit.launchserver.command.handler.CommandHandler.registerCommands(commandHandler, this); @@ -406,24 +404,16 @@ public void restart() { } } - @SuppressWarnings("deprecation") public void registerObject(String name, Object object) { if (object instanceof Reconfigurable) { reconfigurableManager.registerReconfigurable(name, (Reconfigurable) object); } - if (object instanceof NeedGarbageCollection) { - GarbageManager.registerNeedGC((NeedGarbageCollection) object); - } } - @SuppressWarnings("deprecation") public void unregisterObject(String name, Object object) { if (object instanceof Reconfigurable) { reconfigurableManager.unregisterReconfigurable(name); } - if (object instanceof NeedGarbageCollection) { - GarbageManager.unregisterNeedGC((NeedGarbageCollection) object); - } } public void fullyRestart() { diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java index be573f08..8bde3ffc 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServerStarter.java @@ -13,7 +13,6 @@ import pro.gravit.launchserver.auth.core.AuthCoreProvider; import pro.gravit.launchserver.auth.password.PasswordVerifier; import pro.gravit.launchserver.auth.protect.ProtectHandler; -import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider; import pro.gravit.launchserver.auth.session.SessionStorage; import pro.gravit.launchserver.auth.texture.TextureProvider; import pro.gravit.launchserver.components.Component; @@ -204,7 +203,6 @@ public static void registerAll() { WebSocketService.registerResponses(); AuthRequest.registerProviders(); GetAvailabilityAuthRequest.registerProviders(); - HWIDProvider.registerProviders(); OptionalAction.registerProviders(); OptionalTrigger.registerProviders(); SessionStorage.registerProviders(); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java index bffceb7e..cb56f9c9 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/AuthCoreProvider.java @@ -17,13 +17,11 @@ import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware; import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportRegistration; import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportHardware; -import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider; import pro.gravit.launchserver.manangers.AuthManager; import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.response.auth.AuthResponse; import pro.gravit.utils.ProviderMap; import pro.gravit.utils.command.Command; -import pro.gravit.utils.command.CommandException; import pro.gravit.utils.command.SubCommand; import java.io.IOException; @@ -251,7 +249,7 @@ public void invoke(String... args) throws Exception { verifyArgs(args, 2); HardwareReportRequest.HardwareInfo hardware1 = Launcher.gsonManager.gson.fromJson(args[0], HardwareReportRequest.HardwareInfo.class); HardwareReportRequest.HardwareInfo hardware2 = Launcher.gsonManager.gson.fromJson(args[1], HardwareReportRequest.HardwareInfo.class); - HWIDProvider.HardwareInfoCompareResult result = instance.compareHardwareInfo(hardware1, hardware2); + AuthSupportHardware.HardwareInfoCompareResult result = instance.compareHardwareInfo(hardware1, hardware2); if (result == null) { logger.error("Method compareHardwareInfo return null"); return; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/HttpAuthCoreProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/HttpAuthCoreProvider.java index 732f8b95..0b0fd659 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/HttpAuthCoreProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/HttpAuthCoreProvider.java @@ -120,14 +120,22 @@ public AuthManager.AuthReport refreshAccessToken(String refreshToken, AuthRespon @Override public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext context, AuthRequest.AuthPasswordInterface password, boolean minecraftAccess) throws IOException { var result = requester.send(requester.post(authorizeUrl, new AuthorizeRequest(login, context, password, minecraftAccess), - bearerToken), AuthManager.AuthReport.class); + bearerToken), HttpAuthReport.class); if(!result.isSuccessful()) { var error = result.error().error; if(error != null) { throw new AuthException(error); } } - return result.getOrThrow(); + return result.getOrThrow().toAuthReport(); + } + + public record HttpAuthReport(String minecraftAccessToken, String oauthAccessToken, + String oauthRefreshToken, long oauthExpire, + HttpUserSession session) { + public AuthManager.AuthReport toAuthReport() { + return new AuthManager.AuthReport(minecraftAccessToken, oauthAccessToken, oauthRefreshToken, oauthExpire, session); + } } @Override @@ -198,7 +206,7 @@ public void init(LaunchServer server) { if(authorizeUrl == null) { throw new IllegalArgumentException("'authorizeUrl' can't be null"); } - if((checkServerUrl == null && joinServerUrl == null) || updateServerIdUrl == null) { + if(checkServerUrl == null && joinServerUrl == null && updateServerIdUrl == null) { throw new IllegalArgumentException("Please set 'checkServerUrl' and 'joinServerUrl' or 'updateServerIdUrl'"); } } @@ -303,13 +311,13 @@ public Texture getCloakTexture() { public static class HttpUserSession implements UserSession { private String id; - private User user; + private HttpUser user; private long expireIn; public HttpUserSession() { } - public HttpUserSession(String id, User user, long expireIn) { + public HttpUserSession(String id, HttpUser user, long expireIn) { this.id = id; this.user = user; this.expireIn = expireIn; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MemoryAuthCoreProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MemoryAuthCoreProvider.java index c3c83db6..14d17bb7 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MemoryAuthCoreProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MemoryAuthCoreProvider.java @@ -83,7 +83,7 @@ public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext c memory.add(user); } } - if(minecraftAccess) { + if(!minecraftAccess) { return AuthManager.AuthReport.ofOAuth(user.accessToken, null, 0, new MemoryUserSession(user)); } else { return AuthManager.AuthReport.ofOAuthWithMinecraft(user.accessToken, user.accessToken, null, 0, new MemoryUserSession(user)); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MySQLCoreProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MySQLCoreProvider.java index 7842058c..089f78dd 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MySQLCoreProvider.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/MySQLCoreProvider.java @@ -13,7 +13,6 @@ import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware; import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportHardware; import pro.gravit.launchserver.auth.password.PasswordVerifier; -import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider; import pro.gravit.launchserver.manangers.AuthManager; import pro.gravit.launchserver.socket.response.auth.AuthResponse; import pro.gravit.utils.helper.IOHelper; @@ -272,7 +271,7 @@ public UserHardware getHardwareInfoByData(HardwareReportRequest.HardwareInfo inf try (ResultSet set = s.executeQuery()) { while (set.next()) { MySQLUserHardware hw = fetchHardwareInfo(set); - HWIDProvider.HardwareInfoCompareResult result = compareHardwareInfo(hw.getHardwareInfo(), info); + HardwareInfoCompareResult result = compareHardwareInfo(hw.getHardwareInfo(), info); if (result.compareLevel > criticalCompareLevel) { return hw; } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/interfaces/provider/AuthSupportHardware.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/interfaces/provider/AuthSupportHardware.java index 60ba8353..b3f1f761 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/interfaces/provider/AuthSupportHardware.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/core/interfaces/provider/AuthSupportHardware.java @@ -5,7 +5,6 @@ import pro.gravit.launchserver.auth.core.UserSession; import pro.gravit.launchserver.auth.core.interfaces.UserHardware; import pro.gravit.launchserver.auth.core.interfaces.user.UserSupportHardware; -import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider; import pro.gravit.launchserver.helper.DamerauHelper; import java.util.Arrays; @@ -40,8 +39,8 @@ default void normalizeHardwareInfo(HardwareReportRequest.HardwareInfo hardwareIn } //Required normalize HardwareInfo - default HWIDProvider.HardwareInfoCompareResult compareHardwareInfo(HardwareReportRequest.HardwareInfo first, HardwareReportRequest.HardwareInfo second) { - HWIDProvider.HardwareInfoCompareResult result = new HWIDProvider.HardwareInfoCompareResult(); + default HardwareInfoCompareResult compareHardwareInfo(HardwareReportRequest.HardwareInfo first, HardwareReportRequest.HardwareInfo second) { + HardwareInfoCompareResult result = new HardwareInfoCompareResult(); if (first.hwDiskId == null || first.hwDiskId.isEmpty()) result.firstSpoofingLevel += 0.9; if (first.displayId == null || first.displayId.length < 4) result.firstSpoofingLevel += 0.3; if (first.baseboardSerialNumber == null || first.baseboardSerialNumber.trim().isEmpty()) @@ -95,4 +94,10 @@ default HWIDProvider.HardwareInfoCompareResult compareHardwareInfo(HardwareRepor result.compareLevel += 0.05; return result; } + + class HardwareInfoCompareResult { + public double firstSpoofingLevel = 0.0; + public double secondSpoofingLevel = 0.0; + public double compareLevel; + } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/AdvancedProtectHandler.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/AdvancedProtectHandler.java index 520cc9ce..a74aa9c4 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/AdvancedProtectHandler.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/AdvancedProtectHandler.java @@ -9,12 +9,9 @@ import pro.gravit.launcher.events.request.VerifySecureLevelKeyRequestEvent; import pro.gravit.launcher.request.secure.HardwareReportRequest; import pro.gravit.launchserver.LaunchServer; -import pro.gravit.launchserver.Reconfigurable; import pro.gravit.launchserver.auth.AuthProviderPair; import pro.gravit.launchserver.auth.core.interfaces.UserHardware; import pro.gravit.launchserver.auth.core.interfaces.provider.AuthSupportHardware; -import pro.gravit.launchserver.auth.protect.hwid.HWIDException; -import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider; import pro.gravit.launchserver.auth.protect.interfaces.HardwareProtectHandler; import pro.gravit.launchserver.auth.protect.interfaces.JoinServerProtectHandler; import pro.gravit.launchserver.auth.protect.interfaces.SecureProtectHandler; @@ -22,17 +19,13 @@ import pro.gravit.launchserver.socket.response.auth.AuthResponse; import pro.gravit.launchserver.socket.response.auth.RestoreResponse; import pro.gravit.launchserver.socket.response.secure.HardwareReportResponse; -import pro.gravit.utils.command.Command; import java.util.Base64; import java.util.Date; -import java.util.HashMap; -import java.util.Map; -public class AdvancedProtectHandler extends StdProtectHandler implements SecureProtectHandler, HardwareProtectHandler, JoinServerProtectHandler, Reconfigurable { +public class AdvancedProtectHandler extends StdProtectHandler implements SecureProtectHandler, HardwareProtectHandler, JoinServerProtectHandler { private transient final Logger logger = LogManager.getLogger(); public boolean enableHardwareFeature; - public HWIDProvider provider; private transient LaunchServer server; @Override @@ -61,37 +54,28 @@ public void onHardwareReport(HardwareReportResponse response, Client client) { response.sendResult(new HardwareReportRequestEvent(createHardwareToken(client.username, response.hardware))); return; } - try { - if (!client.isAuth || client.trustLevel == null || client.trustLevel.publicKey == null) { - response.sendError("Access denied"); - return; - } - logger.debug("HardwareInfo received"); - { - var authSupportHardware = client.auth.isSupport(AuthSupportHardware.class); - if (authSupportHardware != null) { - UserHardware hardware = authSupportHardware.getHardwareInfoByData(response.hardware); - if (hardware == null) { - hardware = authSupportHardware.createHardwareInfo(response.hardware, client.trustLevel.publicKey); - } else { - authSupportHardware.addPublicKeyToHardwareInfo(hardware, client.trustLevel.publicKey); - } - authSupportHardware.connectUserAndHardware(client.sessionObject, hardware); - if (hardware.isBanned()) { - throw new SecurityException("Your hardware banned"); - } - client.trustLevel.hardwareInfo = hardware.getHardwareInfo(); + if (!client.isAuth || client.trustLevel == null || client.trustLevel.publicKey == null) { + response.sendError("Access denied"); + return; + } + logger.debug("HardwareInfo received"); + { + var authSupportHardware = client.auth.isSupport(AuthSupportHardware.class); + if (authSupportHardware != null) { + UserHardware hardware = authSupportHardware.getHardwareInfoByData(response.hardware); + if (hardware == null) { + hardware = authSupportHardware.createHardwareInfo(response.hardware, client.trustLevel.publicKey); } else { - provider.normalizeHardwareInfo(response.hardware); - boolean needCreate = !provider.addPublicKeyToHardwareInfo(response.hardware, client.trustLevel.publicKey, client); - logger.debug("HardwareInfo needCreate: {}", needCreate ? "true" : "false"); - if (needCreate) - provider.createHardwareInfo(response.hardware, client.trustLevel.publicKey, client); - client.trustLevel.hardwareInfo = response.hardware; + authSupportHardware.addPublicKeyToHardwareInfo(hardware, client.trustLevel.publicKey); } + authSupportHardware.connectUserAndHardware(client.sessionObject, hardware); + if (hardware.isBanned()) { + throw new SecurityException("Your hardware banned"); + } + client.trustLevel.hardwareInfo = hardware.getHardwareInfo(); + } else { + logger.error("AuthCoreProvider not supported hardware"); } - } catch (HWIDException e) { - throw new SecurityException(e.getMessage()); } response.sendResult(new HardwareReportRequestEvent(createHardwareToken(client.username, response.hardware))); } @@ -109,31 +93,14 @@ public VerifySecureLevelKeyRequestEvent onSuccessVerify(Client client) { } client.trustLevel.hardwareInfo = hardware.getHardwareInfo(); authSupportHardware.connectUserAndHardware(client.sessionObject, hardware); - } else if (provider == null) { - logger.warn("HWIDProvider null. HardwareInfo not checked!"); } else { - try { - client.trustLevel.hardwareInfo = provider.findHardwareInfoByPublicKey(client.trustLevel.publicKey, client); - if (client.trustLevel.hardwareInfo == null) //HWID not found? - return new VerifySecureLevelKeyRequestEvent(true, false, createPublicKeyToken(client.username, client.trustLevel.publicKey)); - } catch (HWIDException e) { - throw new SecurityException(e.getMessage()); //Show banned message - } + logger.warn("AuthCoreProvider not supported hardware. HardwareInfo not checked!"); } return new VerifySecureLevelKeyRequestEvent(false, false, createPublicKeyToken(client.username, client.trustLevel.publicKey)); } return new VerifySecureLevelKeyRequestEvent(false, false, createPublicKeyToken(client.username, client.trustLevel.publicKey)); } - @Override - public Map getCommands() { - Map commands = new HashMap<>(); - if (provider instanceof Reconfigurable) { - commands.putAll(((Reconfigurable) provider).getCommands()); - } - return commands; - } - @Override public boolean onJoinServer(String serverID, String username, Client client) { return !enableHardwareFeature || (client.trustLevel != null && client.trustLevel.hardwareInfo != null); @@ -141,17 +108,11 @@ public boolean onJoinServer(String serverID, String username, Client client) { @Override public void init(LaunchServer server) { - if (provider != null) { - provider.init(server); - logger.warn("HWIDProvider deprecated. Please use 'AuthSupportHardware' in AuthCoreProvider"); - } this.server = server; } @Override public void close() { - if (provider != null) - provider.close(); } public String createHardwareToken(String username, HardwareReportRequest.HardwareInfo info) { diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/HWIDException.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/HWIDException.java deleted file mode 100644 index df960144..00000000 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/HWIDException.java +++ /dev/null @@ -1,22 +0,0 @@ -package pro.gravit.launchserver.auth.protect.hwid; - -public class HWIDException extends Exception { - public HWIDException() { - } - - public HWIDException(String message) { - super(message); - } - - public HWIDException(String message, Throwable cause) { - super(message, cause); - } - - public HWIDException(Throwable cause) { - super(cause); - } - - public HWIDException(String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace) { - super(message, cause, enableSuppression, writableStackTrace); - } -} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/HWIDProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/HWIDProvider.java deleted file mode 100644 index 69000516..00000000 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/HWIDProvider.java +++ /dev/null @@ -1,116 +0,0 @@ -package pro.gravit.launchserver.auth.protect.hwid; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import pro.gravit.launcher.request.secure.HardwareReportRequest; -import pro.gravit.launchserver.LaunchServer; -import pro.gravit.launchserver.helper.DamerauHelper; -import pro.gravit.launchserver.socket.Client; -import pro.gravit.utils.ProviderMap; -import pro.gravit.utils.helper.SecurityHelper; - -import java.util.Arrays; - -public abstract class HWIDProvider { - public static final ProviderMap providers = new ProviderMap<>("HWIDProvider"); - private static boolean registredProv = false; - private final Logger logger = LogManager.getLogger(); - - public static void registerProviders() { - if (!registredProv) { - providers.register("memory", MemoryHWIDProvider.class); - providers.register("mysql", MysqlHWIDProvider.class); - providers.register("json", JsonHWIDProvider.class); - registredProv = true; - } - } - - public abstract HardwareReportRequest.HardwareInfo findHardwareInfoByPublicKey(byte[] publicKey, Client client) throws HWIDException; - - public abstract void createHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException; - - public abstract boolean addPublicKeyToHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException; - - public void normalizeHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo) { - if (hardwareInfo.baseboardSerialNumber != null) - hardwareInfo.baseboardSerialNumber = hardwareInfo.baseboardSerialNumber.trim(); - if (hardwareInfo.hwDiskId != null) hardwareInfo.hwDiskId = hardwareInfo.hwDiskId.trim(); - } - - //Required normalize HardwareInfo - public HardwareInfoCompareResult compareHardwareInfo(HardwareReportRequest.HardwareInfo first, HardwareReportRequest.HardwareInfo second) { - HardwareInfoCompareResult result = new HardwareInfoCompareResult(); - if (first.hwDiskId == null || first.hwDiskId.isEmpty()) result.firstSpoofingLevel += 0.9; - if (first.displayId == null || first.displayId.length < 4) result.firstSpoofingLevel += 0.3; - if (first.baseboardSerialNumber == null || first.baseboardSerialNumber.trim().isEmpty()) - result.firstSpoofingLevel += 0.2; - if (second.hwDiskId == null || second.hwDiskId.trim().isEmpty()) result.secondSpoofingLevel += 0.9; - if (second.displayId == null || second.displayId.length < 4) result.secondSpoofingLevel += 0.3; - if (second.baseboardSerialNumber == null || second.baseboardSerialNumber.trim().isEmpty()) - result.secondSpoofingLevel += 0.2; - if (first.hwDiskId != null && second.hwDiskId != null) { - int hwDIskIdRate = DamerauHelper.calculateDistance(first.hwDiskId.toLowerCase(), second.hwDiskId.toLowerCase()); - if (hwDIskIdRate == 0) // 100% compare - { - result.compareLevel += 0.99; - } else if (hwDIskIdRate < 3) //Very small change - { - result.compareLevel += 0.85; - } else if (hwDIskIdRate < (first.hwDiskId.length() + second.hwDiskId.length()) / 4) { - double addLevel = hwDIskIdRate / ((double) (first.hwDiskId.length() + second.hwDiskId.length()) / 2.0); - if (addLevel > 0.0 && addLevel < 0.85) result.compareLevel += addLevel; - } - } - if (first.baseboardSerialNumber != null && second.baseboardSerialNumber != null) { - int baseboardSerialRate = DamerauHelper.calculateDistance(first.baseboardSerialNumber.toLowerCase(), second.baseboardSerialNumber.toLowerCase()); - if (baseboardSerialRate == 0) // 100% compare - { - result.compareLevel += 0.3; - } else if (baseboardSerialRate < 3) //Very small change - { - result.compareLevel += 0.15; - } - } - if (first.displayId != null && second.displayId != null) { - if (Arrays.equals(first.displayId, second.displayId)) { - result.compareLevel += 0.75; - } - } - //Check statistic info - if (first.logicalProcessors == 0 || first.physicalProcessors == 0 || first.logicalProcessors < first.physicalProcessors) //WTF - result.firstSpoofingLevel += 0.9; - if (second.logicalProcessors == 0 || second.physicalProcessors == 0 || second.logicalProcessors < second.physicalProcessors) //WTF - result.secondSpoofingLevel += 0.9; - if (first.physicalProcessors == second.physicalProcessors && first.logicalProcessors == second.logicalProcessors) - result.compareLevel += 0.05; - if (first.battery != second.battery) - result.compareLevel -= 0.05; - if (first.processorMaxFreq == second.processorMaxFreq) - result.compareLevel += 0.1; - if (first.totalMemory == second.totalMemory) - result.compareLevel += 0.1; - if (Math.abs(first.totalMemory - second.totalMemory) < 32 * 1024) - result.compareLevel += 0.05; - return result; - } - - protected void printHardwareInfo(HardwareReportRequest.HardwareInfo info) { - logger.info("[HardwareInfo] Processor: logical {} | physical {} | freq {} | bitness {}", info.logicalProcessors, info.physicalProcessors, info.processorMaxFreq, info.bitness); - logger.info("[HardwareInfo] Memory max: {} | battery {}", info.totalMemory, info.battery ? "true" : "false"); - logger.info("[HardwareInfo] HWDiskID {} | baseboardSerialNumber {} | displayId hash: {}", info.hwDiskId, info.baseboardSerialNumber, SecurityHelper.toHex(SecurityHelper.digest(SecurityHelper.DigestAlgorithm.MD5, info.displayId))); - } - - public void init(LaunchServer server) { - - } - - public void close() { - - } - - public static class HardwareInfoCompareResult { - public double firstSpoofingLevel = 0.0; - public double secondSpoofingLevel = 0.0; - public double compareLevel; - } -} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/JsonHWIDProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/JsonHWIDProvider.java deleted file mode 100644 index 9c2348e2..00000000 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/JsonHWIDProvider.java +++ /dev/null @@ -1,101 +0,0 @@ -package pro.gravit.launchserver.auth.protect.hwid; - -import pro.gravit.launcher.HTTPRequest; -import pro.gravit.launcher.Launcher; -import pro.gravit.launcher.request.secure.HardwareReportRequest; -import pro.gravit.launchserver.socket.Client; - -import java.net.URL; - -public class JsonHWIDProvider extends HWIDProvider { - public URL findHardwareInfoByPublicKeyRequest; - public URL createHardwareInfoRequest; - public URL addPublicKeyToHardwareInfoRequest; - public String apiKey; - - @Override - public HardwareReportRequest.HardwareInfo findHardwareInfoByPublicKey(byte[] publicKey, Client client) throws HWIDException { - try { - RequestFind req = new RequestFind(); - req.publicKey = publicKey; - req.client = client; - req.apiKey = apiKey; - ResultFind r = Launcher.gsonManager.gson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(req), findHardwareInfoByPublicKeyRequest), ResultFind.class); - if (r.error != null) throw new HWIDException(r.error); - return r.info; - } catch (HWIDException t) { - throw t; - } catch (Throwable t) { - throw new HWIDException(t); - } - } - - @Override - public void createHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException { - try { - RequestCreate req = new RequestCreate(); - req.publicKey = publicKey; - req.client = client; - req.hardwareInfo = hardwareInfo; - req.apiKey = apiKey; - ResultCreate r = Launcher.gsonManager.gson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(req), createHardwareInfoRequest), ResultCreate.class); - if (r.error != null) throw new HWIDException(r.error); - } catch (HWIDException t) { - throw t; - } catch (Throwable t) { - throw new HWIDException(t); - } - } - - @Override - public boolean addPublicKeyToHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException { - try { - RequestAddKey req = new RequestAddKey(); - req.publicKey = publicKey; - req.client = client; - req.hardwareInfo = hardwareInfo; - req.apiKey = apiKey; - ResultAddKey r = Launcher.gsonManager.gson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.gson.toJsonTree(req), addPublicKeyToHardwareInfoRequest), ResultAddKey.class); - if (r.error != null) throw new HWIDException(r.error); - return r.success; - } catch (HWIDException t) { - throw t; - } catch (Throwable t) { - throw new HWIDException(t); - } - } - - public static class RequestFind { - public byte[] publicKey; - public Client client; - public String apiKey; - } - - public static class ResultFind { - public String error; - public HardwareReportRequest.HardwareInfo info; - } - - public static class RequestCreate { - public byte[] publicKey; - public Client client; - public HardwareReportRequest.HardwareInfo hardwareInfo; - public String apiKey; - } - - public static class ResultCreate { - public String error; - } - - public static class RequestAddKey { - public byte[] publicKey; - public Client client; - public HardwareReportRequest.HardwareInfo hardwareInfo; - public String apiKey; - } - - public static class ResultAddKey { - public String error; - public boolean success; - } -} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/MemoryHWIDProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/MemoryHWIDProvider.java deleted file mode 100644 index 4524cb3f..00000000 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/MemoryHWIDProvider.java +++ /dev/null @@ -1,100 +0,0 @@ -package pro.gravit.launchserver.auth.protect.hwid; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import pro.gravit.launcher.request.secure.HardwareReportRequest; -import pro.gravit.launchserver.Reconfigurable; -import pro.gravit.launchserver.socket.Client; -import pro.gravit.utils.command.Command; -import pro.gravit.utils.command.SubCommand; -import pro.gravit.utils.helper.SecurityHelper; - -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -public class MemoryHWIDProvider extends HWIDProvider implements Reconfigurable { - private transient final Logger logger = LogManager.getLogger(); - public double warningSpoofingLevel = -1.0; - public double criticalCompareLevel = 1.0; - public transient Set db = ConcurrentHashMap.newKeySet(); - - @Override - public Map getCommands() { - Map commands = new HashMap<>(); - commands.put("hardwarelist", new SubCommand() { - @Override - public void invoke(String... args) { - for (MemoryHWIDEntity e : db) { - printHardwareInfo(e.hardware); - logger.info("ID {} banned {}", e.id, e.banned ? "true" : "false"); - logger.info("PublicKey Hash: {}", SecurityHelper.toHex(SecurityHelper.digest(SecurityHelper.DigestAlgorithm.SHA1, e.publicKey))); - } - } - }); - commands.put("hardwareban", new SubCommand() { - @Override - public void invoke(String... args) throws Exception { - verifyArgs(args, 1); - long id = Long.parseLong(args[0]); - for (MemoryHWIDEntity e : db) { - if (e.id == id) { - e.banned = true; - logger.info("HardwareID {} banned", e.id); - } - } - } - }); - return commands; - } - - @Override - public HardwareReportRequest.HardwareInfo findHardwareInfoByPublicKey(byte[] publicKey, Client client) throws HWIDException { - for (MemoryHWIDEntity e : db) { - if (Arrays.equals(e.publicKey, publicKey)) { - if (e.banned) throw new HWIDException("You HWID banned"); - return e.hardware; - } - } - return null; - } - - @Override - public void createHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) { - db.add(new MemoryHWIDEntity(hardwareInfo, publicKey)); - } - - @Override - public boolean addPublicKeyToHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException { - boolean isAlreadyWarning = false; - for (MemoryHWIDEntity e : db) { - HardwareInfoCompareResult result = compareHardwareInfo(e.hardware, hardwareInfo); - if (warningSpoofingLevel > 0 && result.firstSpoofingLevel > warningSpoofingLevel && !isAlreadyWarning) { - logger.warn("HardwareInfo spoofing level too high: {}", result.firstSpoofingLevel); - isAlreadyWarning = true; - } - if (result.compareLevel > criticalCompareLevel) { - logger.debug("HardwareInfo publicKey change: compareLevel {}", result.compareLevel); - if (e.banned) throw new HWIDException("You HWID banned"); - e.publicKey = publicKey; - return true; - } - } - return false; - } - - static class MemoryHWIDEntity { - public HardwareReportRequest.HardwareInfo hardware; - public byte[] publicKey; - public boolean banned; - public long id; - - public MemoryHWIDEntity(HardwareReportRequest.HardwareInfo hardware, byte[] publicKey) { - this.hardware = hardware; - this.publicKey = publicKey; - this.id = SecurityHelper.newRandom().nextLong(); - } - } -} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/MysqlHWIDProvider.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/MysqlHWIDProvider.java deleted file mode 100644 index e4f6e784..00000000 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/protect/hwid/MysqlHWIDProvider.java +++ /dev/null @@ -1,164 +0,0 @@ -package pro.gravit.launchserver.auth.protect.hwid; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import pro.gravit.launcher.request.secure.HardwareReportRequest; -import pro.gravit.launchserver.LaunchServer; -import pro.gravit.launchserver.auth.MySQLSourceConfig; -import pro.gravit.launchserver.socket.Client; -import pro.gravit.utils.helper.IOHelper; - -import java.io.ByteArrayInputStream; -import java.io.IOException; -import java.sql.*; - -public class MysqlHWIDProvider extends HWIDProvider { - private transient final Logger logger = LogManager.getLogger(); - public MySQLSourceConfig mySQLHolder; - public double warningSpoofingLevel = -1.0; - public double criticalCompareLevel = 1.0; - public String tableHWID = "hwids"; - public String tableHWIDLog = "hwidLog"; - public String tableUsers; - public String usersNameColumn; - public String usersHWIDColumn; - private String sqlFindByPublicKey; - private String sqlFindByHardware; - private String sqlCreateHardware; - private String sqlCreateHWIDLog; - private String sqlUpdateHardware; - private String sqlUpdateUsers; - - @Override - public void init(LaunchServer server) { - sqlFindByPublicKey = String.format("SELECT hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, banned FROM %s WHERE `publicKey` = ?", tableHWID); - sqlFindByHardware = String.format("SELECT hwDiskId, baseboardSerialNumber, displayId, bitness, totalMemory, logicalProcessors, physicalProcessors, processorMaxFreq, battery, id, banned FROM %s", tableHWID); - sqlCreateHardware = String.format("INSERT INTO `%s` (`publickey`, `hwDiskId`, `baseboardSerialNumber`, `displayId`, `bitness`, `totalMemory`, `logicalProcessors`, `physicalProcessors`, `processorMaxFreq`, `battery`, `banned`) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '0')", tableHWID); - sqlCreateHWIDLog = String.format("INSERT INTO %s (`hwidId`, `newPublicKey`) VALUES (?, ?)", tableHWIDLog); - sqlUpdateHardware = String.format("UPDATE %s SET `publicKey` = ? WHERE `id` = ?", tableHWID); - if (tableUsers != null && usersHWIDColumn != null && usersNameColumn != null) { - sqlUpdateUsers = String.format("UPDATE %s SET `%s` = ? WHERE `%s` = ?", tableUsers, usersHWIDColumn, usersNameColumn); - } else { - logger.warn("[MysqlHWIDProvider] Link to users table not configured"); - } - } - - @Override - public HardwareReportRequest.HardwareInfo findHardwareInfoByPublicKey(byte[] publicKey, Client client) throws HWIDException { - try (Connection connection = mySQLHolder.getConnection()) { - PreparedStatement s = connection.prepareStatement(sqlFindByPublicKey); - s.setBlob(1, new ByteArrayInputStream(publicKey)); - ResultSet set = s.executeQuery(); - if (set.next()) { - if (set.getBoolean(11)) //isBanned - { - throw new HWIDException("You HWID banned"); - } - long id = set.getLong(10); - setUserHardwareId(connection, client.username, id); - return fetchHardwareInfo(set); - } else { - return null; - } - } catch (SQLException | IOException throwables) { - logger.error(throwables); - throw new HWIDException("SQL error. Please try again later"); - } - } - - private HardwareReportRequest.HardwareInfo fetchHardwareInfo(ResultSet set) throws SQLException, IOException { - HardwareReportRequest.HardwareInfo hardwareInfo = new HardwareReportRequest.HardwareInfo(); - hardwareInfo.hwDiskId = set.getString(1); - hardwareInfo.baseboardSerialNumber = set.getString(2); - Blob displayId = set.getBlob(3); - hardwareInfo.displayId = displayId == null ? null : IOHelper.read(displayId.getBinaryStream()); - hardwareInfo.bitness = set.getInt(4); - hardwareInfo.totalMemory = set.getLong(5); - hardwareInfo.logicalProcessors = set.getInt(6); - hardwareInfo.physicalProcessors = set.getInt(7); - hardwareInfo.processorMaxFreq = set.getLong(8); - hardwareInfo.battery = set.getBoolean(9); - return hardwareInfo; - } - - @Override - public void createHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException { - try (Connection connection = mySQLHolder.getConnection()) { - PreparedStatement s = connection.prepareStatement(sqlCreateHardware, Statement.RETURN_GENERATED_KEYS); - s.setBlob(1, new ByteArrayInputStream(publicKey)); - s.setString(2, hardwareInfo.hwDiskId); - s.setString(3, hardwareInfo.baseboardSerialNumber); - s.setBlob(4, hardwareInfo.displayId == null ? null : new ByteArrayInputStream(hardwareInfo.displayId)); - s.setInt(5, hardwareInfo.bitness); - s.setLong(6, hardwareInfo.totalMemory); - s.setInt(7, hardwareInfo.logicalProcessors); - s.setInt(8, hardwareInfo.physicalProcessors); - s.setLong(9, hardwareInfo.processorMaxFreq); - s.setBoolean(10, hardwareInfo.battery); - s.executeUpdate(); - try (ResultSet generatedKeys = s.getGeneratedKeys()) { - if (generatedKeys.next()) { - writeHwidLog(connection, generatedKeys.getLong(1), publicKey); - setUserHardwareId(connection, client.username, generatedKeys.getLong(1)); - } - } - } catch (SQLException throwables) { - logger.error(throwables); - throw new HWIDException("SQL error. Please try again later"); - } - } - - @Override - public boolean addPublicKeyToHardwareInfo(HardwareReportRequest.HardwareInfo hardwareInfo, byte[] publicKey, Client client) throws HWIDException { - try (Connection connection = mySQLHolder.getConnection()) { - PreparedStatement s = connection.prepareStatement(sqlFindByHardware); - ResultSet set = s.executeQuery(); - while (set.next()) { - HardwareReportRequest.HardwareInfo hw = fetchHardwareInfo(set); - long id = set.getLong(10); - HardwareInfoCompareResult result = compareHardwareInfo(hw, hardwareInfo); - if (result.compareLevel > criticalCompareLevel) { - if (set.getBoolean(11)) //isBanned - { - throw new HWIDException("You HWID banned"); - } - writeHwidLog(connection, id, publicKey); - changePublicKey(connection, id, publicKey); - setUserHardwareId(connection, client.username, id); - return true; - } - } - } catch (SQLException | IOException throwables) { - logger.error(throwables); - throw new HWIDException("SQL error. Please try again later"); - } - return false; - } - - private void changePublicKey(Connection connection, long id, byte[] publicKey) throws SQLException { - PreparedStatement s = connection.prepareStatement(sqlUpdateHardware); - s.setBlob(1, new ByteArrayInputStream(publicKey)); - s.setLong(2, id); - s.executeUpdate(); - } - - private void writeHwidLog(Connection connection, long hwidId, byte[] newPublicKey) throws SQLException { - PreparedStatement s = connection.prepareStatement(sqlCreateHWIDLog); - s.setLong(1, hwidId); - s.setBlob(2, new ByteArrayInputStream(newPublicKey)); - s.executeUpdate(); - } - - private void setUserHardwareId(Connection connection, String username, long hwidId) throws SQLException { - if (sqlUpdateUsers == null || username == null) return; - PreparedStatement s = connection.prepareStatement(sqlUpdateUsers); - s.setLong(1, hwidId); - s.setString(2, username); - s.executeUpdate(); - } - - @Override - public void close() { - mySQLHolder.close(); - } -} diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/session/MemorySessionStorage.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/session/MemorySessionStorage.java index 75bbc304..a341c13f 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/session/MemorySessionStorage.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/session/MemorySessionStorage.java @@ -3,7 +3,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import pro.gravit.launcher.Launcher; -import pro.gravit.launcher.NeedGarbageCollection; import pro.gravit.launchserver.LaunchServer; import pro.gravit.utils.helper.IOHelper; @@ -12,14 +11,13 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.UUID; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Stream; -public class MemorySessionStorage extends SessionStorage implements NeedGarbageCollection, AutoCloseable { +public class MemorySessionStorage extends SessionStorage implements AutoCloseable { private transient final Map clientSet = new ConcurrentHashMap<>(128); private transient final Map> uuidIndex = new ConcurrentHashMap<>(32); @@ -32,7 +30,6 @@ public void init(LaunchServer server) { super.init(server); if (autoDump) { loadSessionsData(); - garbageCollection(); } } @@ -144,26 +141,9 @@ private void removeUuidFromIndexSet(Set set, Entry e, UUID session) { } } - @Override - public void garbageCollection() { - long time = System.currentTimeMillis(); - long session_timeout = server.config.netty.performance.sessionLifetimeMs; - Set to_delete = new HashSet<>(32); - clientSet.forEach((uuid, entry) -> { - long timestamp = entry.timestamp; - if (timestamp + session_timeout < time) - to_delete.add(uuid); - }); - for (UUID session : to_delete) { - deleteSession(session); - } - to_delete.clear(); - } - @Override public void close() { if (autoDump) { - garbageCollection(); dumpSessionsData(); } } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/handler/CommandHandler.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/handler/CommandHandler.java index 52c58a72..e794977d 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/handler/CommandHandler.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/handler/CommandHandler.java @@ -16,6 +16,7 @@ import pro.gravit.utils.command.basic.HelpCommand; public abstract class CommandHandler extends pro.gravit.utils.command.CommandHandler { + @SuppressWarnings("deprecation") public static void registerCommands(pro.gravit.utils.command.CommandHandler handler, LaunchServer server) { BaseCommandCategory basic = new BaseCommandCategory(); // Register basic commands diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/PingServersCommand.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/PingServersCommand.java index 988207e5..368c71de 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/PingServersCommand.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/PingServersCommand.java @@ -6,6 +6,7 @@ import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.command.Command; +@Deprecated public class PingServersCommand extends Command { private transient final Logger logger = LogManager.getLogger(); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/SecurityCheckCommand.java b/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/SecurityCheckCommand.java index 486cc769..30db46a8 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/SecurityCheckCommand.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/command/service/SecurityCheckCommand.java @@ -85,12 +85,6 @@ public void invoke(String... args) { printCheckResult("netty.address", "", true); } - if (config.netty.sendExceptionEnabled) { - printCheckResult("netty.sendExceptionEnabled", "recommend \"false\" in production", false); - } else { - printCheckResult("netty.sendExceptionEnabled", "", true); - } - if (config.netty.launcherURL.startsWith("http://")) { printCheckResult("netty.launcherUrl", "launcher jar download connection not secure", false); } else if (config.netty.launcherURL.startsWith("https://")) { diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/components/AbstractLimiter.java b/LaunchServer/src/main/java/pro/gravit/launchserver/components/AbstractLimiter.java index 5a599089..121dd00a 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/components/AbstractLimiter.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/components/AbstractLimiter.java @@ -2,7 +2,6 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import pro.gravit.launcher.NeedGarbageCollection; import pro.gravit.launchserver.Reconfigurable; import pro.gravit.utils.command.Command; import pro.gravit.utils.command.SubCommand; @@ -12,7 +11,7 @@ import java.util.List; import java.util.Map; -public abstract class AbstractLimiter extends Component implements NeedGarbageCollection, Reconfigurable { +public abstract class AbstractLimiter extends Component implements Reconfigurable { public final List exclude = new ArrayList<>(); protected final transient Map map = new HashMap<>(); private transient final Logger logger = LogManager.getLogger(); @@ -64,7 +63,6 @@ public void invoke(String... args) { protected abstract T getFromString(String str); - @Override public void garbageCollection() { long time = System.currentTimeMillis(); map.entrySet().removeIf((e) -> e.getValue().time + rateLimitMillis < time); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/components/AuthLimiterComponent.java b/LaunchServer/src/main/java/pro/gravit/launchserver/components/AuthLimiterComponent.java index cda63163..dc0b5ced 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/components/AuthLimiterComponent.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/components/AuthLimiterComponent.java @@ -1,12 +1,11 @@ package pro.gravit.launchserver.components; -import pro.gravit.launcher.NeedGarbageCollection; import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.response.auth.AuthResponse; import pro.gravit.utils.HookException; -public class AuthLimiterComponent extends IPLimiter implements NeedGarbageCollection, AutoCloseable { +public class AuthLimiterComponent extends IPLimiter implements AutoCloseable { public String message; private transient LaunchServer srv; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/components/ProGuardComponent.java b/LaunchServer/src/main/java/pro/gravit/launchserver/components/ProGuardComponent.java index 3fe10d7c..a28b65d3 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/components/ProGuardComponent.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/components/ProGuardComponent.java @@ -144,6 +144,7 @@ public Path process(Path inputFile) throws IOException { logger.debug("JMods resolved in {}", jfxPath.toString()); } else { logger.error("JavaFX jmods not found. May be install OpenJFX?"); + jfxPath = null; } ConfigurationParser parser = new ConfigurationParser(proguardConf.buildConfig(inputFile, outputJar, jfxPath == null ? new Path[0] : new Path[]{jfxPath}), proguardConf.proguard.toFile(), System.getProperties()); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/components/RegLimiterComponent.java b/LaunchServer/src/main/java/pro/gravit/launchserver/components/RegLimiterComponent.java index 2ca25fd7..7452c560 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/components/RegLimiterComponent.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/components/RegLimiterComponent.java @@ -1,6 +1,5 @@ package pro.gravit.launchserver.components; -import pro.gravit.launcher.NeedGarbageCollection; import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.manangers.hook.AuthHookManager; import pro.gravit.utils.HookException; @@ -8,7 +7,7 @@ import java.util.ArrayList; import java.util.List; -public class RegLimiterComponent extends IPLimiter implements NeedGarbageCollection, AutoCloseable { +public class RegLimiterComponent extends IPLimiter implements AutoCloseable { public transient LaunchServer launchServer; public String message; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/config/LaunchServerConfig.java b/LaunchServer/src/main/java/pro/gravit/launchserver/config/LaunchServerConfig.java index 3ba63457..d7cd9bb7 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/config/LaunchServerConfig.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/config/LaunchServerConfig.java @@ -77,7 +77,6 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) { newConfig.netty = new NettyConfig(); newConfig.netty.fileServerEnabled = true; - newConfig.netty.sendExceptionEnabled = false; newConfig.netty.binds = new NettyBindAddress[]{new NettyBindAddress("0.0.0.0", 9274)}; newConfig.netty.performance = new NettyPerformanceConfig(); try { @@ -286,6 +285,7 @@ public static class LauncherConf { public static class NettyConfig { public boolean fileServerEnabled; + @Deprecated public boolean sendExceptionEnabled; public boolean ipForwarding; public boolean disableWebApiInterface; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/LaunchServerGsonManager.java b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/LaunchServerGsonManager.java index fdadd9f5..f94dbd85 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/LaunchServerGsonManager.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/LaunchServerGsonManager.java @@ -1,6 +1,7 @@ package pro.gravit.launchserver.manangers; import com.google.gson.GsonBuilder; +import marcono1234.gson.recordadapter.RecordTypeAdapterFactory; import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent; import pro.gravit.launcher.managers.GsonManager; import pro.gravit.launcher.modules.events.PreGsonPhase; @@ -13,7 +14,6 @@ import pro.gravit.launchserver.auth.core.AuthCoreProvider; import pro.gravit.launchserver.auth.password.PasswordVerifier; import pro.gravit.launchserver.auth.protect.ProtectHandler; -import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider; import pro.gravit.launchserver.auth.session.SessionStorage; import pro.gravit.launchserver.auth.texture.TextureProvider; import pro.gravit.launchserver.components.Component; @@ -33,6 +33,7 @@ public LaunchServerGsonManager(LaunchServerModulesManager modulesManager) { @Override public void registerAdapters(GsonBuilder builder) { super.registerAdapters(builder); + builder.registerTypeAdapterFactory(RecordTypeAdapterFactory.DEFAULT); builder.registerTypeAdapter(TextureProvider.class, new UniversalJsonAdapter<>(TextureProvider.providers)); builder.registerTypeAdapter(AuthCoreProvider.class, new UniversalJsonAdapter<>(AuthCoreProvider.providers)); builder.registerTypeAdapter(PasswordVerifier.class, new UniversalJsonAdapter<>(PasswordVerifier.providers)); @@ -42,7 +43,6 @@ public void registerAdapters(GsonBuilder builder) { builder.registerTypeAdapter(WebSocketEvent.class, new JsonResultSerializeAdapter()); builder.registerTypeAdapter(AuthRequest.AuthPasswordInterface.class, new UniversalJsonAdapter<>(AuthRequest.providers)); builder.registerTypeAdapter(GetAvailabilityAuthRequestEvent.AuthAvailabilityDetails.class, new UniversalJsonAdapter<>(GetAvailabilityAuthRequest.providers)); - builder.registerTypeAdapter(HWIDProvider.class, new UniversalJsonAdapter<>(HWIDProvider.providers)); builder.registerTypeAdapter(OptionalAction.class, new UniversalJsonAdapter<>(OptionalAction.providers)); builder.registerTypeAdapter(OptionalTrigger.class, new UniversalJsonAdapter<>(OptionalTrigger.providers)); builder.registerTypeAdapter(SessionStorage.class, new UniversalJsonAdapter<>(SessionStorage.providers)); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/PingServerManager.java b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/PingServerManager.java index 7a56985f..624d40e0 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/PingServerManager.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/PingServerManager.java @@ -7,6 +7,7 @@ import java.util.HashMap; import java.util.Map; +@Deprecated public class PingServerManager { public static final long REPORT_EXPIRED_TIME = 20 * 1000; public final Map map = new HashMap<>(); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java index 3a4dd648..7be2f9ef 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java @@ -1,7 +1,6 @@ package pro.gravit.launchserver.manangers; import pro.gravit.launcher.Launcher; -import pro.gravit.launcher.NeedGarbageCollection; import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.socket.Client; import pro.gravit.utils.HookSet; @@ -11,7 +10,7 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; -public class SessionManager implements NeedGarbageCollection { +public class SessionManager { private final LaunchServer server; public HookSet clientRestoreHook = new HookSet<>(); @@ -57,10 +56,6 @@ private Client restoreFromString(byte[] data) { return result; } - @Override - public void garbageCollection() { - } - public Client getClient(UUID session) { if (session == null) return null; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java index 0df4ad31..32d252e9 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java @@ -65,6 +65,7 @@ public WebSocketService(ChannelGroup channels, LaunchServer server) { this.gson = Launcher.gsonManager.gson; } + @SuppressWarnings("deprecation") public static void registerResponses() { providers.register("auth", AuthResponse.class); providers.register("checkServer", CheckServerResponse.class); @@ -165,11 +166,7 @@ void process(ChannelHandlerContext ctx, WebSocketServerResponse response, Client } catch (Exception e) { logger.error("WebSocket request processing failed", e); RequestEvent event; - if (server.config.netty.sendExceptionEnabled) { - event = new ExceptionEvent(e); - } else { - event = new ErrorRequestEvent("Fatal server error. Contact administrator"); - } + event = new ErrorRequestEvent("Fatal server error. Contact administrator"); if (response instanceof SimpleResponse) { event.requestUUID = ((SimpleResponse) response).requestUUID; } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/management/PingServerReportResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/management/PingServerReportResponse.java index f7c5fcdf..60ab706c 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/management/PingServerReportResponse.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/management/PingServerReportResponse.java @@ -6,6 +6,7 @@ import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.response.SimpleResponse; +@Deprecated public class PingServerReportResponse extends SimpleResponse { public PingServerReportRequest.PingServerReport data; public String name; diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/management/PingServerResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/management/PingServerResponse.java index 2917a938..dfac108a 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/management/PingServerResponse.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/management/PingServerResponse.java @@ -11,6 +11,7 @@ import java.util.List; import java.util.Map; +@Deprecated public class PingServerResponse extends SimpleResponse { public List serverNames; //May be null diff --git a/Launcher/src/main/java/pro/gravit/launcher/BasicLauncherEventHandler.java b/Launcher/src/main/java/pro/gravit/launcher/BasicLauncherEventHandler.java index 4421bc4f..a1246bb0 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/BasicLauncherEventHandler.java +++ b/Launcher/src/main/java/pro/gravit/launcher/BasicLauncherEventHandler.java @@ -5,11 +5,12 @@ import pro.gravit.launcher.events.NotificationEvent; import pro.gravit.launcher.events.request.SecurityReportRequestEvent; import pro.gravit.launcher.request.Request; +import pro.gravit.launcher.request.RequestService; import pro.gravit.launcher.request.WebSocketEvent; import pro.gravit.launcher.request.websockets.ClientWebSocketService; import pro.gravit.utils.helper.LogHelper; -public class BasicLauncherEventHandler implements ClientWebSocketService.EventHandler { +public class BasicLauncherEventHandler implements RequestService.EventHandler { @Override public boolean eventHandle(T event) { diff --git a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java index 07ae298b..561d966a 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java +++ b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java @@ -6,6 +6,7 @@ import pro.gravit.launcher.client.events.ClientPreGuiPhase; import pro.gravit.launcher.console.GetPublicKeyCommand; import pro.gravit.launcher.console.SignDataCommand; +import pro.gravit.launcher.events.request.*; import pro.gravit.launcher.guard.LauncherGuardInterface; import pro.gravit.launcher.guard.LauncherGuardManager; import pro.gravit.launcher.guard.LauncherNoGuard; @@ -14,13 +15,21 @@ import pro.gravit.launcher.gui.RuntimeProvider; import pro.gravit.launcher.managers.ClientGsonManager; import pro.gravit.launcher.managers.ConsoleManager; +import pro.gravit.launcher.modules.events.OfflineModeEvent; import pro.gravit.launcher.modules.events.PreConfigPhase; import pro.gravit.launcher.profiles.optional.actions.OptionalAction; import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger; import pro.gravit.launcher.request.Request; import pro.gravit.launcher.request.RequestException; -import pro.gravit.launcher.request.auth.AuthRequest; -import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest; +import pro.gravit.launcher.request.RequestService; +import pro.gravit.launcher.request.auth.*; +import pro.gravit.launcher.request.auth.details.AuthLoginOnlyDetails; +import pro.gravit.launcher.request.management.FeaturesRequest; +import pro.gravit.launcher.request.secure.GetSecureLevelInfoRequest; +import pro.gravit.launcher.request.secure.SecurityReportRequest; +import pro.gravit.launcher.request.update.LauncherRequest; +import pro.gravit.launcher.request.websockets.ClientWebSocketService; +import pro.gravit.launcher.request.websockets.OfflineRequestService; import pro.gravit.launcher.request.websockets.StdWebSocketService; import pro.gravit.launcher.utils.NativeJVMHalt; import pro.gravit.utils.helper.*; @@ -33,7 +42,9 @@ import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPublicKey; import java.security.spec.InvalidKeySpecException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Objects; import java.util.concurrent.atomic.AtomicBoolean; @@ -142,6 +153,35 @@ public static LauncherGuardInterface tryGetStdGuard() { return null; } + public static RequestService initOffline() { + OfflineRequestService service = new OfflineRequestService(); + applyBasicOfflineProcessors(service); + OfflineModeEvent event = new OfflineModeEvent(service); + modulesManager.invokeEvent(event); + return event.service; + } + + public static void applyBasicOfflineProcessors(OfflineRequestService service) { + service.registerRequestProcessor(LauncherRequest.class, (r) -> new LauncherRequestEvent(false, (String) null)); + service.registerRequestProcessor(CheckServerRequest.class, (r) -> { + throw new RequestException("CheckServer disabled in offline mode"); + }); + service.registerRequestProcessor(GetAvailabilityAuthRequest.class, (r) -> { + List details = new ArrayList<>(); + details.add(new AuthLoginOnlyDetails()); + GetAvailabilityAuthRequestEvent.AuthAvailability authAvailability = new GetAvailabilityAuthRequestEvent.AuthAvailability("offline", "Offline Mode", details); + List list = new ArrayList<>(1); + list.add(authAvailability); + return new GetAvailabilityAuthRequestEvent(list); + }); + service.registerRequestProcessor(JoinServerRequest.class, (r) -> new JoinServerRequestEvent(false)); + service.registerRequestProcessor(ExitRequest.class, (r) -> new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT)); + service.registerRequestProcessor(SetProfileRequest.class, (r) -> new SetProfileRequestEvent(null)); + service.registerRequestProcessor(FeaturesRequest.class, (r) -> new FeaturesRequestEvent()); + service.registerRequestProcessor(GetSecureLevelInfoRequest.class, (r) -> new GetSecureLevelInfoRequestEvent(null, false)); + service.registerRequestProcessor(SecurityReportRequest.class, (r) -> new SecurityReportRequestEvent(SecurityReportRequestEvent.ReportAction.NONE)); + } + public static LauncherEngine clientInstance() { return new LauncherEngine(true); } @@ -189,21 +229,33 @@ public void start(String... args) throws Throwable { if (runtimeProvider == null) runtimeProvider = new NoRuntimeProvider(); runtimeProvider.init(clientInstance); //runtimeProvider.preLoad(); - if (Request.service == null) { + if (!Request.isAvailable()) { String address = Launcher.getConfig().address; LogHelper.debug("Start async connection to %s", address); - Request.service = StdWebSocketService.initWebSockets(address, true); - Request.service.reconnectCallback = () -> - { - LogHelper.debug("WebSocket connect closed. Try reconnect"); - try { - Request.reconnect(); - } catch (Exception e) { + RequestService service; + try { + service = StdWebSocketService.initWebSockets(address).get(); + } catch (Throwable e) { + if(LogHelper.isDebugEnabled()) { LogHelper.error(e); - throw new RequestException("Connection failed", e); } - }; - Request.service.registerEventHandler(new BasicLauncherEventHandler()); + LogHelper.warning("Launcher in offline mode"); + service = initOffline(); + } + Request.setRequestService(service); + if(service instanceof StdWebSocketService) { + ((StdWebSocketService) service).reconnectCallback = () -> + { + LogHelper.debug("WebSocket connect closed. Try reconnect"); + try { + Request.reconnect(); + } catch (Exception e) { + LogHelper.error(e); + throw new RequestException("Connection failed", e); + } + }; + } + service.registerEventHandler(new BasicLauncherEventHandler()); } Objects.requireNonNull(args, "args"); if (started.getAndSet(true)) diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java index a4101444..2c6e72b4 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java @@ -4,12 +4,16 @@ import pro.gravit.launcher.api.AuthService; import pro.gravit.launcher.api.ClientService; import pro.gravit.launcher.client.events.client.*; +import pro.gravit.launcher.events.request.ProfileByUUIDRequestEvent; +import pro.gravit.launcher.events.request.ProfileByUsernameRequestEvent; import pro.gravit.launcher.guard.LauncherGuardManager; import pro.gravit.launcher.hasher.FileNameMatcher; import pro.gravit.launcher.hasher.HashedDir; import pro.gravit.launcher.hasher.HashedEntry; import pro.gravit.launcher.managers.ClientGsonManager; import pro.gravit.launcher.managers.ConsoleManager; +import pro.gravit.launcher.modules.LauncherModulesManager; +import pro.gravit.launcher.modules.events.OfflineModeEvent; import pro.gravit.launcher.modules.events.PreConfigPhase; import pro.gravit.launcher.patches.FMLPatcher; import pro.gravit.launcher.profiles.ClientProfile; @@ -19,8 +23,14 @@ import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger; import pro.gravit.launcher.request.Request; import pro.gravit.launcher.request.RequestException; +import pro.gravit.launcher.request.RequestService; import pro.gravit.launcher.request.auth.AuthRequest; import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest; +import pro.gravit.launcher.request.uuid.BatchProfileByUsernameRequest; +import pro.gravit.launcher.request.uuid.ProfileByUUIDRequest; +import pro.gravit.launcher.request.uuid.ProfileByUsernameRequest; +import pro.gravit.launcher.request.websockets.OfflineRequestService; +import pro.gravit.launcher.request.websockets.StdWebSocketService; import pro.gravit.launcher.serialize.HInput; import pro.gravit.launcher.utils.DirWatcher; import pro.gravit.utils.helper.*; @@ -112,19 +122,26 @@ public static void main(String[] args) throws Throwable { List classpath = resolveClassPath(clientDir, params.actions, params.profile).map(IOHelper::toURL).collect(Collectors.toList()); // Start client with WatchService monitoring boolean digest = !profile.isUpdateFastCheck(); - LogHelper.debug("Restore sessions"); - Request.restore(); - Request.service.registerEventHandler(new BasicLauncherEventHandler()); - Request.service.reconnectCallback = () -> - { - LogHelper.debug("WebSocket connect closed. Try reconnect"); - try { - Request.reconnect(); - } catch (Exception e) { - LogHelper.error(e); - throw new RequestException("Connection failed", e); - } - }; + RequestService service; + if(params.offlineMode) { + service = initOffline(LauncherEngine.modulesManager, params); + } else { + service = StdWebSocketService.initWebSockets(Launcher.getConfig().address).get(); + LogHelper.debug("Restore sessions"); + Request.restore(); + service.registerEventHandler(new BasicLauncherEventHandler()); + ((StdWebSocketService) service).reconnectCallback = () -> + { + LogHelper.debug("WebSocket connect closed. Try reconnect"); + try { + Request.reconnect(); + } catch (Exception e) { + LogHelper.error(e); + throw new RequestException("Connection failed", e); + } + }; + } + Request.setRequestService(service); ClientProfile.ClassLoaderConfig classLoaderConfig = profile.getClassLoaderConfig(); if (classLoaderConfig == ClientProfile.ClassLoaderConfig.LAUNCHER) { ClientClassLoader classLoader = new ClientClassLoader(classpath.toArray(new URL[0]), ClassLoader.getSystemClassLoader()); @@ -200,6 +217,30 @@ private static void initGson(ClientModuleManager moduleManager) { Launcher.gsonManager.initGson(); } + public static RequestService initOffline(LauncherModulesManager modulesManager, ClientLauncherProcess.ClientParams params) { + OfflineRequestService service = new OfflineRequestService(); + LauncherEngine.applyBasicOfflineProcessors(service); + applyClientOfflineProcessors(service, params); + OfflineModeEvent event = new OfflineModeEvent(service); + modulesManager.invokeEvent(event); + return event.service; + } + + public static void applyClientOfflineProcessors(OfflineRequestService service, ClientLauncherProcess.ClientParams params) { + service.registerRequestProcessor(ProfileByUsernameRequest.class, (r) -> { + if(params.playerProfile.username.equals(r.username)) { + return new ProfileByUsernameRequestEvent(params.playerProfile); + } + throw new RequestException("User not found"); + }); + service.registerRequestProcessor(ProfileByUUIDRequest.class, (r) -> { + if(params.playerProfile.uuid.equals(r.uuid)) { + return new ProfileByUUIDRequestEvent(params.playerProfile); + } + throw new RequestException("User not found"); + }); + } + public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher, boolean digest) throws IOException { //if (matcher != null) // matcher = matcher.verifyOnly(); @@ -314,7 +355,7 @@ private static void launch(ClientProfile profile, ClientLauncherProcess.ClientPa runMethod.invoke(); } } - MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class)).asFixedArity(); + MethodHandle mainMethod = MethodHandles.lookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class)).asFixedArity(); Launcher.LAUNCHED.set(true); JVMHelper.fullGC(); // Invoke main method diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java index 1dbe37ab..f2a6e111 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java @@ -281,6 +281,8 @@ public static class ClientParams { public Map extendedTokens; + public boolean offlineMode; + public transient HashedDir assetHDir; public transient HashedDir clientHDir; diff --git a/Launcher/src/main/java/pro/gravit/launcher/debug/DebugMain.java b/Launcher/src/main/java/pro/gravit/launcher/debug/DebugMain.java index 2f5c88f8..27b1348b 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/debug/DebugMain.java +++ b/Launcher/src/main/java/pro/gravit/launcher/debug/DebugMain.java @@ -7,7 +7,12 @@ import pro.gravit.launcher.client.ClientModuleManager; import pro.gravit.launcher.managers.ConsoleManager; import pro.gravit.launcher.modules.LauncherModule; +import pro.gravit.launcher.modules.events.OfflineModeEvent; import pro.gravit.launcher.modules.events.PreConfigPhase; +import pro.gravit.launcher.request.Request; +import pro.gravit.launcher.request.RequestService; +import pro.gravit.launcher.request.websockets.OfflineRequestService; +import pro.gravit.launcher.request.websockets.StdWebSocketService; import pro.gravit.utils.helper.LogHelper; import java.lang.invoke.MethodHandles; @@ -22,6 +27,7 @@ public class DebugMain { public static String webSocketURL = System.getProperty("launcherdebug.websocket", "ws://localhost:9274/api"); public static String projectName = System.getProperty("launcherdebug.projectname", "Minecraft"); public static String unlockKey = System.getProperty("launcherdebug.unlockkey", "0000"); + public static boolean offlineMode = Boolean.getBoolean("launcherdebug.offlinemode"); public static String[] moduleClasses = System.getProperty("launcherdebug.modules", "").split(","); public static String[] moduleFiles = System.getProperty("launcherdebug.modulefiles", "").split(","); public static LauncherConfig.LauncherEnvironment environment = LauncherConfig.LauncherEnvironment.valueOf(System.getProperty("launcherdebug.env", "STD")); @@ -50,6 +56,17 @@ public static void main(String[] args) throws Throwable { LauncherEngine.initGson(LauncherEngine.modulesManager); ConsoleManager.initConsole(); LauncherEngine.modulesManager.invokeEvent(new PreConfigPhase()); + RequestService service; + if(offlineMode) { + OfflineRequestService offlineRequestService = new OfflineRequestService(); + LauncherEngine.applyBasicOfflineProcessors(offlineRequestService); + OfflineModeEvent event = new OfflineModeEvent(offlineRequestService); + LauncherEngine.modulesManager.invokeEvent(event); + service = event.service; + } else { + service = StdWebSocketService.initWebSockets(webSocketURL).get(); + } + Request.setRequestService(service); LogHelper.debug("Initialization LauncherEngine"); LauncherEngine instance = LauncherEngine.newInstance(false); instance.start(args); diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/events/ExceptionEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/events/ExceptionEvent.java index 910d8395..f91a01e7 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/events/ExceptionEvent.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/events/ExceptionEvent.java @@ -2,6 +2,7 @@ import pro.gravit.launcher.LauncherNetworkAPI; +@Deprecated public class ExceptionEvent extends RequestEvent { @LauncherNetworkAPI public final String message; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/events/PingEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/events/PingEvent.java index 6a26ea14..8921d2ed 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/events/PingEvent.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/events/PingEvent.java @@ -2,5 +2,6 @@ //Пустое событие //Все обработчики обязаны его игнорировать +@Deprecated public final class PingEvent { } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/events/SignalEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/events/SignalEvent.java index c4ff91f6..98a21d24 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/events/SignalEvent.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/events/SignalEvent.java @@ -4,6 +4,7 @@ import pro.gravit.launcher.request.WebSocketEvent; //Используется, что бы послать короткое сообщение, которое вмещается в int +@Deprecated public class SignalEvent implements WebSocketEvent { @LauncherNetworkAPI public final int signal; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/GetSecureLevelInfoRequestEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/GetSecureLevelInfoRequestEvent.java index bd5bbf6e..2b8fa051 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/GetSecureLevelInfoRequestEvent.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/GetSecureLevelInfoRequestEvent.java @@ -10,6 +10,11 @@ public GetSecureLevelInfoRequestEvent(byte[] verifySecureKey) { this.verifySecureKey = verifySecureKey; } + public GetSecureLevelInfoRequestEvent(byte[] verifySecureKey, boolean enabled) { + this.verifySecureKey = verifySecureKey; + this.enabled = enabled; + } + @Override public String getType() { return "getSecureLevelInfo"; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/LogEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/LogEvent.java index c09a607e..6f3e4b49 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/LogEvent.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/LogEvent.java @@ -3,6 +3,7 @@ import pro.gravit.launcher.LauncherNetworkAPI; import pro.gravit.launcher.request.WebSocketEvent; +@Deprecated public class LogEvent implements WebSocketEvent { @LauncherNetworkAPI public final String string; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/PingServerReportRequestEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/PingServerReportRequestEvent.java index ed45ae0f..395dbe32 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/PingServerReportRequestEvent.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/PingServerReportRequestEvent.java @@ -2,6 +2,7 @@ import pro.gravit.launcher.events.RequestEvent; +@Deprecated public class PingServerReportRequestEvent extends RequestEvent { @Override public String getType() { diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/PingServerRequestEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/PingServerRequestEvent.java index c4bf8558..2f8277d3 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/PingServerRequestEvent.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/PingServerRequestEvent.java @@ -5,6 +5,7 @@ import java.util.Map; +@Deprecated public class PingServerRequestEvent extends RequestEvent { public Map serverMap; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/RegisterRequestEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/RegisterRequestEvent.java index f08506c8..1d98c4de 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/RegisterRequestEvent.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/RegisterRequestEvent.java @@ -2,6 +2,7 @@ import pro.gravit.launcher.events.RequestEvent; +@Deprecated public class RegisterRequestEvent extends RequestEvent { @Override public String getType() { diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/modules/events/OfflineModeEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/modules/events/OfflineModeEvent.java new file mode 100644 index 00000000..28a92579 --- /dev/null +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/modules/events/OfflineModeEvent.java @@ -0,0 +1,12 @@ +package pro.gravit.launcher.modules.events; + +import pro.gravit.launcher.modules.LauncherModule; +import pro.gravit.launcher.request.RequestService; + +public class OfflineModeEvent extends LauncherModule.Event { + public RequestService service; + + public OfflineModeEvent(RequestService service) { + this.service = service; + } +} diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java index 10153950..e28bde03 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java @@ -19,7 +19,9 @@ public abstract class Request implements WebSocketRequest { private static final List extendedTokenCallbacks = new ArrayList<>(4); private static final List> oauthChangeHandlers = new ArrayList<>(4); + @Deprecated public static StdWebSocketService service; + private static RequestService requestService; private static UUID session; private static AuthRequestEvent.OAuthRequestEvent oauth; private static Map extendedTokens; @@ -29,6 +31,21 @@ public abstract class Request implements WebSocketRequ public final UUID requestUUID = UUID.randomUUID(); private transient final AtomicBoolean started = new AtomicBoolean(false); + public static void setRequestService(RequestService service) { + requestService = service; + if(service instanceof StdWebSocketService) { + Request.service = (StdWebSocketService) service; + } + } + + public static RequestService getRequestService() { + return requestService; + } + + public static boolean isAvailable() { + return requestService != null; + } + public static UUID getSession() { return Request.session; } @@ -197,18 +214,26 @@ public void removeOAuthChangeHandler(BiConsumer CompletableFuture request(Request request) throws IOException; + void registerEventHandler(EventHandler handler); + void unregisterEventHandler(EventHandler handler); + default T requestSync(Request request) throws IOException { + try { + return request(request).get(); + } catch (InterruptedException e) { + throw new RequestException("Request interrupted"); + } catch (ExecutionException e) { + Throwable cause = e.getCause(); + if (cause instanceof IOException) + throw (IOException) e.getCause(); + else { + throw new RequestException(cause); + } + } + } + + boolean isClosed(); + + @FunctionalInterface + public interface EventHandler { + /** + * @param event processing event + * @param event type + * @return false - continue, true - stop + */ + boolean eventHandle(T event); + } +} + diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/auth/AuthRequest.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/auth/AuthRequest.java index cddccefe..679ae5bb 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/auth/AuthRequest.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/auth/AuthRequest.java @@ -11,15 +11,15 @@ public final class AuthRequest extends Request implements WebS public static final ProviderMap providers = new ProviderMap<>(); private static boolean registerProviders = false; @LauncherNetworkAPI - private final String login; + public final String login; @LauncherNetworkAPI - private final AuthPasswordInterface password; + public final AuthPasswordInterface password; @LauncherNetworkAPI - private final String auth_id; + public final String auth_id; @LauncherNetworkAPI - private final boolean getSession; + public final boolean getSession; @LauncherNetworkAPI - private final ConnectTypes authType; + public final ConnectTypes authType; public AuthRequest(String login, String password, String auth_id, ConnectTypes authType) { this.login = login; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/update/LauncherRequest.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/update/LauncherRequest.java index b492e5f0..68f55dac 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/update/LauncherRequest.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/update/LauncherRequest.java @@ -4,6 +4,7 @@ import pro.gravit.launcher.LauncherNetworkAPI; import pro.gravit.launcher.events.request.LauncherRequestEvent; import pro.gravit.launcher.request.Request; +import pro.gravit.launcher.request.RequestService; import pro.gravit.launcher.request.websockets.StdWebSocketService; import pro.gravit.launcher.request.websockets.WebSocketRequest; import pro.gravit.utils.helper.IOHelper; @@ -88,7 +89,7 @@ public static void update(LauncherRequestEvent result) throws IOException { } @Override - public LauncherRequestEvent requestDo(StdWebSocketService service) throws Exception { + public LauncherRequestEvent requestDo(RequestService service) throws Exception { LauncherRequestEvent result = super.request(service); if (result.needUpdate) update(result); return result; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientJSONPoint.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientJSONPoint.java index c2018379..c2dda916 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientJSONPoint.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientJSONPoint.java @@ -24,6 +24,8 @@ import java.security.KeyStoreException; import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateException; +import java.util.concurrent.CompletableFuture; +import java.util.function.Consumer; public abstract class ClientJSONPoint { @@ -94,16 +96,26 @@ public void open() throws Exception { webSocketClientHandler.handshakeFuture().sync(); } - public void openAsync(Runnable onConnect) { + public void openAsync(Runnable onConnect, Consumer onFail) { //System.out.println("WebSocket Client connecting"); webSocketClientHandler = new WebSocketClientHandler( WebSocketClientHandshakerFactory.newHandshaker( uri, WebSocketVersion.V13, null, false, EmptyHttpHeaders.INSTANCE, 12800000), this); ChannelFuture future = bootstrap.connect(uri.getHost(), port); - future.addListener((e) -> { - ch = future.channel(); - webSocketClientHandler.handshakeFuture().addListener((e1) -> onConnect.run()); + future.addListener((l) -> { + if(l.isSuccess()) { + ch = future.channel(); + webSocketClientHandler.handshakeFuture().addListener((e) -> { + if(e.isSuccess()) { + onConnect.run(); + } else { + onFail.accept(webSocketClientHandler.handshakeFuture().cause()); + } + }); + } else { + onFail.accept(future.cause()); + } }); } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java index 44ca653f..7768daea 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java @@ -27,6 +27,7 @@ public abstract class ClientWebSocketService extends ClientJSONPoint { public static final ProviderMap results = new ProviderMap<>(); public static final ProviderMap requests = new ProviderMap<>(); + private static boolean resultsRegistered = false; public final Gson gson; public final Boolean onConnect; public OnCloseCallback onCloseCallback; @@ -81,39 +82,43 @@ public void registerRequests() { } + @SuppressWarnings("deprecation") public void registerResults() { - results.register("auth", AuthRequestEvent.class); - results.register("checkServer", CheckServerRequestEvent.class); - results.register("joinServer", JoinServerRequestEvent.class); - results.register("launcher", LauncherRequestEvent.class); - results.register("profileByUsername", ProfileByUsernameRequestEvent.class); - results.register("profileByUUID", ProfileByUUIDRequestEvent.class); - results.register("batchProfileByUsername", BatchProfileByUsernameRequestEvent.class); - results.register("profiles", ProfilesRequestEvent.class); - results.register("setProfile", SetProfileRequestEvent.class); - results.register("updateList", UpdateListRequestEvent.class); - results.register("error", ErrorRequestEvent.class); - results.register("update", UpdateRequestEvent.class); - results.register("restoreSession", RestoreSessionRequestEvent.class); - results.register("log", LogEvent.class); - results.register("getAvailabilityAuth", GetAvailabilityAuthRequestEvent.class); - results.register("exception", ExceptionEvent.class); - results.register("register", RegisterRequestEvent.class); - results.register("notification", NotificationEvent.class); - results.register("signal", SignalEvent.class); - results.register("exit", ExitRequestEvent.class); - results.register("getSecureLevelInfo", GetSecureLevelInfoRequestEvent.class); - results.register("verifySecureLevelKey", VerifySecureLevelKeyRequestEvent.class); - results.register("securityReport", SecurityReportRequestEvent.class); - results.register("hardwareReport", HardwareReportRequestEvent.class); - results.register("serverStatus", ServerStatusRequestEvent.class); - results.register("pingServerReport", PingServerReportRequestEvent.class); - results.register("pingServer", PingServerRequestEvent.class); - results.register("currentUser", CurrentUserRequestEvent.class); - results.register("features", FeaturesRequestEvent.class); - results.register("refreshToken", RefreshTokenRequestEvent.class); - results.register("restore", RestoreRequestEvent.class); - results.register("additionalData", AdditionalDataRequestEvent.class); + if(!resultsRegistered) { + results.register("auth", AuthRequestEvent.class); + results.register("checkServer", CheckServerRequestEvent.class); + results.register("joinServer", JoinServerRequestEvent.class); + results.register("launcher", LauncherRequestEvent.class); + results.register("profileByUsername", ProfileByUsernameRequestEvent.class); + results.register("profileByUUID", ProfileByUUIDRequestEvent.class); + results.register("batchProfileByUsername", BatchProfileByUsernameRequestEvent.class); + results.register("profiles", ProfilesRequestEvent.class); + results.register("setProfile", SetProfileRequestEvent.class); + results.register("updateList", UpdateListRequestEvent.class); + results.register("error", ErrorRequestEvent.class); + results.register("update", UpdateRequestEvent.class); + results.register("restoreSession", RestoreSessionRequestEvent.class); + results.register("log", LogEvent.class); + results.register("getAvailabilityAuth", GetAvailabilityAuthRequestEvent.class); + results.register("exception", ExceptionEvent.class); + results.register("register", RegisterRequestEvent.class); + results.register("notification", NotificationEvent.class); + results.register("signal", SignalEvent.class); + results.register("exit", ExitRequestEvent.class); + results.register("getSecureLevelInfo", GetSecureLevelInfoRequestEvent.class); + results.register("verifySecureLevelKey", VerifySecureLevelKeyRequestEvent.class); + results.register("securityReport", SecurityReportRequestEvent.class); + results.register("hardwareReport", HardwareReportRequestEvent.class); + results.register("serverStatus", ServerStatusRequestEvent.class); + results.register("pingServerReport", PingServerReportRequestEvent.class); + results.register("pingServer", PingServerRequestEvent.class); + results.register("currentUser", CurrentUserRequestEvent.class); + results.register("features", FeaturesRequestEvent.class); + results.register("refreshToken", RefreshTokenRequestEvent.class); + results.register("restore", RestoreRequestEvent.class); + results.register("additionalData", AdditionalDataRequestEvent.class); + resultsRegistered = true; + } } public void waitIfNotConnected() { diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/OfflineRequestService.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/OfflineRequestService.java new file mode 100644 index 00000000..fd353447 --- /dev/null +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/OfflineRequestService.java @@ -0,0 +1,73 @@ +package pro.gravit.launcher.request.websockets; + +import pro.gravit.launcher.Launcher; +import pro.gravit.launcher.request.Request; +import pro.gravit.launcher.request.RequestException; +import pro.gravit.launcher.request.RequestService; +import pro.gravit.launcher.request.WebSocketEvent; +import pro.gravit.utils.helper.LogHelper; + +import java.io.IOException; +import java.util.HashSet; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; + +public class OfflineRequestService implements RequestService { + private final HashSet eventHandlers = new HashSet<>(); + private final Map, RequestProcessor> processors = new ConcurrentHashMap<>(); + @Override + @SuppressWarnings("unchecked") + public CompletableFuture request(Request request) throws IOException { + RequestProcessor> processor = (RequestProcessor>) processors.get(request.getClass()); + CompletableFuture future = new CompletableFuture<>(); + if(processor == null) { + future.completeExceptionally(new RequestException(String.format("Offline mode not support '%s'", request.getType()))); + return future; + } + if(LogHelper.isDevEnabled()) { + LogHelper.dev("Request %s: %s", request.getType(), Launcher.gsonManager.gson.toJson(request)); + } + try { + T event = processor.process(request); + if(LogHelper.isDevEnabled()) { + LogHelper.dev("Response %s: %s", event.getType(), Launcher.gsonManager.gson.toJson(event)); + } + future.complete(event); + } catch (Throwable e) { + if(e instanceof RequestException) { + future.completeExceptionally(e); + } else { + future.completeExceptionally(new RequestException(e)); + } + } + return future; + } + + @Override + public void registerEventHandler(EventHandler handler) { + eventHandlers.add(handler); + } + + @Override + public void unregisterEventHandler(EventHandler handler) { + eventHandlers.remove(handler); + } + + @Override + public boolean isClosed() { + return false; + } + + public void registerRequestProcessor(Class requestClazz, RequestProcessor function) { + processors.put(requestClazz, function); + } + + public void unregisterRequestProcessor(Class> requestClazz) { + processors.remove(requestClazz); + } + + public interface RequestProcessor { + T process(V request) throws RequestException; + } +} diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/StdWebSocketService.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/StdWebSocketService.java index 6816ad64..2c0664ee 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/StdWebSocketService.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/StdWebSocketService.java @@ -5,6 +5,7 @@ import pro.gravit.launcher.events.request.ErrorRequestEvent; import pro.gravit.launcher.request.Request; import pro.gravit.launcher.request.RequestException; +import pro.gravit.launcher.request.RequestService; import pro.gravit.launcher.request.WebSocketEvent; import pro.gravit.utils.helper.JVMHelper; import pro.gravit.utils.helper.LogHelper; @@ -17,16 +18,17 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ExecutionException; -public class StdWebSocketService extends ClientWebSocketService { +public class StdWebSocketService extends ClientWebSocketService implements RequestService { @SuppressWarnings("rawtypes") private final ConcurrentHashMap futureMap = new ConcurrentHashMap<>(); - private final HashSet eventHandlers = new HashSet<>(); + private final HashSet eventHandlers = new HashSet<>(); + private final HashSet legacyEventHandlers = new HashSet<>(); public StdWebSocketService(String address) throws SSLException { super(address); } - public static StdWebSocketService initWebSockets(String address, boolean async) { + public static CompletableFuture initWebSockets(String address) throws Exception { StdWebSocketService service; try { service = new StdWebSocketService(address); @@ -35,43 +37,46 @@ public static StdWebSocketService initWebSockets(String address, boolean async) } service.registerResults(); service.registerRequests(); - if (!async) { - try { - service.open(); - } catch (Exception e) { - LogHelper.error(e); - } - } else { - service.openAsync(() -> { - }); - } - JVMHelper.RUNTIME.addShutdownHook(new Thread(() -> { - try { - //if(service.isOpen()) - // service.closeBlocking(); - service.close(); - } catch (InterruptedException e) { - LogHelper.error(e); - } - })); - return service; + CompletableFuture future = new CompletableFuture<>(); + service.openAsync(() -> { + future.complete(service); + JVMHelper.RUNTIME.addShutdownHook(new Thread(() -> { + try { + //if(service.isOpen()) + // service.closeBlocking(); + service.close(); + } catch (InterruptedException e) { + LogHelper.error(e); + } + })); + }, (error) -> { + future.completeExceptionally(error); + }); + return future; } - public void registerEventHandler(EventHandler handler) { - eventHandlers.add(handler); + + + @Deprecated + public void registerEventHandler(ClientWebSocketService.EventHandler handler) { + legacyEventHandlers.add(handler); } - public void unregisterEventHandler(EventHandler handler) { - eventHandlers.remove(handler); + @Deprecated + public void unregisterEventHandler(ClientWebSocketService.EventHandler handler) { + legacyEventHandlers.remove(handler); } public void processEventHandlers(T event) { - for (EventHandler handler : eventHandlers) { + for (RequestService.EventHandler handler : eventHandlers) { + if (handler.eventHandle(event)) return; + } + for (ClientWebSocketService.EventHandler handler : legacyEventHandlers) { if (handler.eventHandle(event)) return; } } - @SuppressWarnings("unchecked") + @SuppressWarnings({"unchecked", "deprecation"}) public void eventHandle(T webSocketEvent) { if (webSocketEvent instanceof RequestEvent) { RequestEvent event = (RequestEvent) webSocketEvent; @@ -110,6 +115,16 @@ public CompletableFuture request(Request reques return result; } + @Override + public void registerEventHandler(RequestService.EventHandler handler) { + eventHandlers.add(handler); + } + + @Override + public void unregisterEventHandler(RequestService.EventHandler handler) { + eventHandlers.remove(handler); + } + public T requestSync(Request request) throws IOException { try { return request(request).get(); @@ -124,4 +139,9 @@ public T requestSync(Request request) throws IOExc } } } + + @Override + public boolean isClosed() { + return isClosed; + } } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/VoidRequestService.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/VoidRequestService.java new file mode 100644 index 00000000..e08214c2 --- /dev/null +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/VoidRequestService.java @@ -0,0 +1,43 @@ +package pro.gravit.launcher.request.websockets; + +import pro.gravit.launcher.request.Request; +import pro.gravit.launcher.request.RequestException; +import pro.gravit.launcher.request.RequestService; +import pro.gravit.launcher.request.WebSocketEvent; + +import java.io.IOException; +import java.util.concurrent.CompletableFuture; + +public class VoidRequestService implements RequestService { + private final Throwable ex; + + public VoidRequestService(Throwable ex) { + this.ex = ex; + } + + public VoidRequestService() { + this.ex = null; + } + + @Override + public CompletableFuture request(Request request) throws IOException { + CompletableFuture future = new CompletableFuture<>(); + future.completeExceptionally(ex != null ? ex : new RequestException("Connection fail")); + return future; + } + + @Override + public void registerEventHandler(EventHandler handler) { + + } + + @Override + public void unregisterEventHandler(EventHandler handler) { + + } + + @Override + public boolean isClosed() { + return true; + } +} diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/WebSocketClientHandler.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/WebSocketClientHandler.java index df633e6f..a3982161 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/WebSocketClientHandler.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/WebSocketClientHandler.java @@ -77,17 +77,15 @@ else if (frame instanceof BinaryWebSocketFrame) { // uncomment to print request // logger.info(frame.content().toString()); } - } @Override public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) { - LogHelper.error(cause); - if (!handshakeFuture.isDone()) { handshakeFuture.setFailure(cause); + } else { + LogHelper.error(cause); } - ctx.close(); } } \ No newline at end of file diff --git a/LauncherCore/src/main/java/pro/gravit/launcher/NeedGarbageCollection.java b/LauncherCore/src/main/java/pro/gravit/launcher/NeedGarbageCollection.java deleted file mode 100644 index 1dfeca49..00000000 --- a/LauncherCore/src/main/java/pro/gravit/launcher/NeedGarbageCollection.java +++ /dev/null @@ -1,10 +0,0 @@ -package pro.gravit.launcher; - -/** - * Determines whether this object requires periodic garbage collection by the gc command - * This interface has nothing to do with java garbage collection. - */ -@FunctionalInterface -public interface NeedGarbageCollection { - void garbageCollection(); -} diff --git a/LauncherCore/src/main/java/pro/gravit/launcher/managers/GarbageManager.java b/LauncherCore/src/main/java/pro/gravit/launcher/managers/GarbageManager.java deleted file mode 100644 index 9726d81d..00000000 --- a/LauncherCore/src/main/java/pro/gravit/launcher/managers/GarbageManager.java +++ /dev/null @@ -1,48 +0,0 @@ -package pro.gravit.launcher.managers; - -import pro.gravit.launcher.NeedGarbageCollection; - -import java.util.HashSet; -import java.util.Set; -import java.util.Timer; -import java.util.TimerTask; - -@Deprecated -public class GarbageManager { - private static final Timer timer = new Timer("GarbageTimer"); - private static final Set NEED_GARBARE_COLLECTION = new HashSet<>(); - - public static void gc() { - for (Entry gc : NEED_GARBARE_COLLECTION) - gc.invoke.garbageCollection(); - } - - public static void registerNeedGC(NeedGarbageCollection gc) { - NEED_GARBARE_COLLECTION.add(new Entry(gc, 0L)); - } - - public static void registerNeedGC(NeedGarbageCollection gc, long time) { - TimerTask task = new TimerTask() { - @Override - public void run() { - gc.garbageCollection(); - } - }; - timer.schedule(task, time); - NEED_GARBARE_COLLECTION.add(new Entry(gc, time)); - } - - public static void unregisterNeedGC(NeedGarbageCollection gc) { - NEED_GARBARE_COLLECTION.removeIf(e -> e.invoke == gc); - } - - static class Entry { - final NeedGarbageCollection invoke; - final long timer; - - public Entry(NeedGarbageCollection invoke, long timer) { - this.invoke = invoke; - this.timer = timer; - } - } -} diff --git a/LauncherCore/src/main/java/pro/gravit/utils/Version.java b/LauncherCore/src/main/java/pro/gravit/utils/Version.java index 601a65bf..8b437b54 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/Version.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/Version.java @@ -6,7 +6,7 @@ public final class Version implements Comparable { public static final int MAJOR = 5; public static final int MINOR = 2; - public static final int PATCH = 5; + public static final int PATCH = 6; public static final int BUILD = 1; public static final Version.Type RELEASE = Type.STABLE; public final int major; diff --git a/LauncherCore/src/main/java/pro/gravit/utils/command/basic/GCCommand.java b/LauncherCore/src/main/java/pro/gravit/utils/command/basic/GCCommand.java index bb00782e..96b128b9 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/command/basic/GCCommand.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/command/basic/GCCommand.java @@ -1,6 +1,5 @@ package pro.gravit.utils.command.basic; -import pro.gravit.launcher.managers.GarbageManager; import pro.gravit.utils.command.Command; import pro.gravit.utils.helper.JVMHelper; import pro.gravit.utils.helper.LogHelper; diff --git a/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java b/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java index 22e1f27b..a0505386 100644 --- a/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java +++ b/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java @@ -17,6 +17,7 @@ import pro.gravit.launcher.request.auth.GetAvailabilityAuthRequest; import pro.gravit.launcher.request.auth.RestoreRequest; import pro.gravit.launcher.request.update.ProfilesRequest; +import pro.gravit.launcher.request.websockets.StdWebSocketService; import pro.gravit.launcher.server.setup.ServerWrapperSetup; import pro.gravit.utils.PublicURLClassLoader; import pro.gravit.utils.helper.IOHelper; @@ -112,6 +113,18 @@ public void run(String... args) throws Throwable { updateLauncherConfig(); if (config.env != null) Launcher.applyLauncherEnv(config.env); else Launcher.applyLauncherEnv(LauncherConfig.LauncherEnvironment.STD); + StdWebSocketService service = StdWebSocketService.initWebSockets(config.address).get(); + service.reconnectCallback = () -> + { + LogHelper.debug("WebSocket connect closed. Try reconnect"); + try { + Request.reconnect(); + getProfiles(); + } catch (Exception e) { + LogHelper.error(e); + } + }; + Request.setRequestService(service); if (config.logFile != null) LogHelper.addOutput(IOHelper.newWriter(Paths.get(config.logFile), true)); { restore(); @@ -153,16 +166,6 @@ public void run(String... args) throws Throwable { if (loader != null) mainClass = Class.forName(classname, true, loader); else mainClass = Class.forName(classname); MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class)); - Request.service.reconnectCallback = () -> - { - LogHelper.debug("WebSocket connect closed. Try reconnect"); - try { - Request.reconnect(); - getProfiles(); - } catch (Exception e) { - LogHelper.error(e); - } - }; LogHelper.info("ServerWrapper: LaunchServer address: %s. Title: %s", config.address, Launcher.profile != null ? Launcher.profile.getTitle() : "unknown"); LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name); LogHelper.info("Start Minecraft Server"); diff --git a/ServerWrapper/src/main/java/pro/gravit/launcher/server/setup/ServerWrapperSetup.java b/ServerWrapper/src/main/java/pro/gravit/launcher/server/setup/ServerWrapperSetup.java index 3e08610d..b173e439 100644 --- a/ServerWrapper/src/main/java/pro/gravit/launcher/server/setup/ServerWrapperSetup.java +++ b/ServerWrapper/src/main/java/pro/gravit/launcher/server/setup/ServerWrapperSetup.java @@ -1,12 +1,14 @@ package pro.gravit.launcher.server.setup; import pro.gravit.launcher.request.Request; +import pro.gravit.launcher.request.websockets.StdWebSocketService; import pro.gravit.launcher.server.ServerWrapper; import pro.gravit.utils.PublicURLClassLoader; import pro.gravit.utils.helper.IOHelper; import pro.gravit.utils.helper.JVMHelper; import pro.gravit.utils.helper.LogHelper; +import java.io.Closeable; import java.io.IOException; import java.io.Writer; import java.net.URL; @@ -56,9 +58,17 @@ public void run() throws Exception { wrapper.config.serverName = commands.commandHandler.readLine(); wrapper.config.mainclass = mainClassName; for (int i = 0; i < 10; ++i) { - if(Request.service == null || Request.service.isClosed) { + if(!Request.isAvailable() || Request.getRequestService().isClosed()) { System.out.println("Print launchserver websocket host( ws://host:port/api ):"); wrapper.config.address = commands.commandHandler.readLine(); + StdWebSocketService service; + try { + service = StdWebSocketService.initWebSockets(wrapper.config.address).get(); + } catch (Throwable e) { + LogHelper.error(e); + continue; + } + Request.setRequestService(service); } System.out.println("Print server token:"); String checkServerToken = commands.commandHandler.readLine(); @@ -70,8 +80,8 @@ public void run() throws Exception { break; } catch (Throwable e) { LogHelper.error(e); - if(!Request.service.isClosed) { - Request.service.close(); + if(Request.isAvailable() && Request.getRequestService() instanceof AutoCloseable) { + ((AutoCloseable) Request.getRequestService()).close(); } } } diff --git a/build.gradle b/build.gradle index 3cdcbab6..82b01e65 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ id 'org.openjfx.javafxplugin' version '0.0.10' apply false } group = 'pro.gravit.launcher' -version = '5.2.5' +version = '5.2.6' apply from: 'props.gradle' @@ -27,6 +27,9 @@ maven { url "https://jcenter.bintray.com/" } + maven { + url "https://jitpack.io/" + } } jar { diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index a0f7639f..fbce071a 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew index bc07847d..1b6c7873 100755 --- a/gradlew +++ b/gradlew @@ -69,18 +69,18 @@ app_path=$0 # Need this for daisy-chained symlinks. while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] do - ls=$(ls -ld "$app_path") - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -APP_HOME=$(cd "${APP_HOME:-./}" && pwd -P) || exit +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit APP_NAME="Gradle" APP_BASE_NAME=${0##*/} @@ -91,15 +91,15 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum -warn() { - echo "$*" +warn () { + echo "$*" } >&2 -die() { - echo - echo "$*" - echo - exit 1 +die () { + echo + echo "$*" + echo + exit 1 } >&2 # OS specific support (must be 'true' or 'false'). @@ -107,52 +107,51 @@ cygwin=false msys=false darwin=false nonstop=false -case "$(uname)" in #( -CYGWIN*) cygwin=true ;; #( -Darwin*) darwin=true ;; #( -MSYS* | MINGW*) msys=true ;; #( -NONSTOP*) nonstop=true ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ]; then - if [ -x "$JAVA_HOME/jre/sh/java" ]; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ]; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME Please set the JAVA_HOME variable in your environment to match the location of your Java installation." - fi + fi else - JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi # Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop"; then - case $MAX_FD in #( - max*) - MAX_FD=$(ulimit -H -n) || - warn "Could not query maximum file descriptor limit" - ;; - esac - case $MAX_FD in #( - '' | soft) : ;; #( - *) - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - ;; - esac +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi # Collect all arguments for the java command, stacking in reverse order: @@ -164,36 +163,34 @@ fi # * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys"; then - APP_HOME=$(cygpath --path --mixed "$APP_HOME") - CLASSPATH=$(cygpath --path --mixed "$CLASSPATH") +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) - JAVACMD=$(cygpath --unix "$JAVACMD") + JAVACMD=$( cygpath --unix "$JAVACMD" ) - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg; do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) - t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] - ;; #( - *) false ;; - esac - then - arg=$(cygpath --path --ignore --mixed "$arg") - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done fi # Collect all arguments for the java command; @@ -203,10 +200,10 @@ fi # * put everything else in single quotes, so that it's not re-expanded. set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -classpath "$CLASSPATH" \ - org.gradle.wrapper.GradleWrapperMain \ - "$@" + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" # Use "xargs" to parse quoted args. # @@ -228,10 +225,10 @@ set -- \ # eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' -)" '"$@"' + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/props.gradle b/props.gradle index c85b8551..5a85c822 100644 --- a/props.gradle +++ b/props.gradle @@ -8,7 +8,7 @@ verJline = '3.20.0' verJwt = '0.11.2' verBcprov = '1.69' - verGson = '2.8.8' + verGson = '2.8.9' verBcpkix = '1.69' verSlf4j = '1.7.32' verLog4j = '2.14.1'