diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java index 96238c73..1b6d8e03 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/LaunchServer.java @@ -91,16 +91,38 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurable { - public void reload() throws Exception { - config.close(); + public enum ReloadType + { + NO_AUTH, + NO_COMPONENTS, + FULL + } + + public void reload(ReloadType type) throws Exception { + config.close(type); + AuthProviderPair[] pairs = null; + if(type.equals(ReloadType.NO_AUTH)) + { + pairs = config.auth; + } LogHelper.info("Reading LaunchServer config file"); try (BufferedReader reader = IOHelper.newReader(configFile)) { config = Launcher.gsonManager.gson.fromJson(reader, Config.class); } config.server = this; + if(type.equals(ReloadType.NO_AUTH)) + { + config.auth = pairs; + } config.verify(); - config.init(); - if (config.components != null) { + config.init(type); + if (type.equals(ReloadType.FULL) && config.components != null) { + LogHelper.debug("PreInit components"); + config.components.forEach((k, v) -> { + LogHelper.subDebug("PreInit component %s", k); + v.preInit(this); + }); + LogHelper.debug("PreInit components successful"); LogHelper.debug("Init components"); config.components.forEach((k, v) -> { LogHelper.subDebug("Init component %s", k); @@ -124,7 +146,26 @@ public Map getCommands() { SubCommand reload = new SubCommand() { @Override public void invoke(String... args) throws Exception { - reload(); + if(args.length == 0) + { + reload(ReloadType.FULL); + return; + } + switch (args[0]) + { + case "full": + reload(ReloadType.FULL); + break; + case "no_auth": + reload(ReloadType.NO_AUTH); + break; + case "no_components": + reload(ReloadType.NO_COMPONENTS); + break; + default: + reload(ReloadType.FULL);; + break; + } } }; commands.put("reload", reload); @@ -229,7 +270,7 @@ public void verify() { } } - public void init() { + public void init(ReloadType type) { Launcher.applyLauncherEnv(env); for (AuthProviderPair provider : auth) { provider.init(server); @@ -241,34 +282,53 @@ public void init() { if (protectHandler != null) { protectHandler.checkLaunchServerLicense(); } - if (components != null) { - LogHelper.debug("PreInit components"); - components.forEach((k, v) -> { - LogHelper.subDebug("PreInit component %s", k); - v.preInit(server); + if(components != null) + { + components.forEach((k,v) -> { + server.registerObject("component.".concat(k), v); }); - LogHelper.debug("PreInit components successful"); } server.registerObject("permissionsHandler", permissionsHandler); server.registerObject("hwidHandler", hwidHandler); - for (int i = 0; i < auth.length; ++i) { - AuthProviderPair pair = auth[i]; - server.registerObject("auth.".concat(pair.name).concat(".provider"), pair.provider); - server.registerObject("auth.".concat(pair.name).concat(".handler"), pair.handler); - server.registerObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider); + if(!type.equals(ReloadType.NO_AUTH)) + { + for (int i = 0; i < auth.length; ++i) { + AuthProviderPair pair = auth[i]; + server.registerObject("auth.".concat(pair.name).concat(".provider"), pair.provider); + server.registerObject("auth.".concat(pair.name).concat(".handler"), pair.handler); + server.registerObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider); + } } + Arrays.stream(mirrors).forEach(server.mirrorManager::addMirror); } - public void close() { + public void close(ReloadType type) { try { server.unregisterObject("permissionsHandler", permissionsHandler); server.unregisterObject("hwidHandler", hwidHandler); - for (AuthProviderPair pair : auth) { - server.unregisterObject("auth.".concat(pair.name).concat(".provider"), pair.provider); - server.unregisterObject("auth.".concat(pair.name).concat(".handler"), pair.handler); - server.unregisterObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider); + if(!type.equals(ReloadType.NO_AUTH)) + { + for (AuthProviderPair pair : auth) { + server.unregisterObject("auth.".concat(pair.name).concat(".provider"), pair.provider); + server.unregisterObject("auth.".concat(pair.name).concat(".handler"), pair.handler); + server.unregisterObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider); + } + } + if(type.equals(ReloadType.FULL)) + { + components.forEach((k, component) -> { + server.unregisterObject("component.".concat(k), component); + if(component instanceof AutoCloseable) + { + try { + ((AutoCloseable) component).close(); + } catch (Exception e) { + LogHelper.error(e); + } + } + }); } } catch (Exception e) { LogHelper.error(e); @@ -618,6 +678,14 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException } runtime.verify(); config.verify(); + if (config.components != null) { + LogHelper.debug("PreInit components"); + config.components.forEach((k, v) -> { + LogHelper.subDebug("PreInit component %s", k); + v.preInit(this); + }); + LogHelper.debug("PreInit components successful"); + } // build hooks, anti-brutforce and other buildHookManager = new BuildHookManager(); @@ -665,7 +733,7 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException } } } - config.init(); + config.init(ReloadType.FULL); registerObject("launchServer", this); GarbageManager.registerNeedGC(sessionManager); @@ -763,7 +831,7 @@ public void buildLauncherBinaries() throws IOException { public void close() { // Close handlers & providers - config.close(); + config.close(ReloadType.FULL); modulesManager.close(); LogHelper.info("Save LaunchServer runtime config"); try (Writer writer = IOHelper.newWriter(runtimeConfigFile)) { @@ -838,12 +906,12 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException { newConfig.components = new HashMap<>(); AuthLimiterComponent authLimiterComponent = new AuthLimiterComponent(); authLimiterComponent.rateLimit = 3; - authLimiterComponent.rateLimitMilis = 8000; + authLimiterComponent.rateLimitMillis = 8000; authLimiterComponent.message = "Превышен лимит авторизаций"; newConfig.components.put("authLimiter", authLimiterComponent); RegLimiterComponent regLimiterComponent = new RegLimiterComponent(); regLimiterComponent.rateLimit = 3; - regLimiterComponent.rateLimitMilis = 1000 * 60 * 60 * 10; //Блок на 10 часов + regLimiterComponent.rateLimitMillis = 1000 * 60 * 60 * 10; //Блок на 10 часов regLimiterComponent.message = "Превышен лимит регистраций"; newConfig.components.put("regLimiter", regLimiterComponent); 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 c3ebb9ca..0d629039 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/components/AbstractLimiter.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/components/AbstractLimiter.java @@ -1,23 +1,21 @@ package pro.gravit.launchserver.components; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import pro.gravit.launcher.NeedGarbageCollection; -public class AbstractLimiter implements NeedGarbageCollection { - public final int maxTrys; - public final int banMillis; - - public AbstractLimiter(int maxTrys, int banMillis) { - this.maxTrys = maxTrys; - this.banMillis = banMillis; - } +public abstract class AbstractLimiter extends Component implements NeedGarbageCollection { + public int rateLimit; + public int rateLimitMillis; + public List exclude = new ArrayList<>(); @Override public void garbageCollection() { long time = System.currentTimeMillis(); - map.entrySet().removeIf((e) -> e.getValue().time + banMillis < time); + map.entrySet().removeIf((e) -> e.getValue().time + rateLimitMillis < time); } class LimitEntry @@ -35,9 +33,10 @@ public LimitEntry() { trys = 0; } } - protected Map map = new HashMap<>(); + protected transient Map map = new HashMap<>(); public boolean check(T address) { + if(exclude.contains(address)) return true; LimitEntry entry = map.get(address); if(entry == null) { @@ -47,13 +46,13 @@ public boolean check(T address) else { long time = System.currentTimeMillis(); - if(entry.trys < maxTrys) + if(entry.trys < rateLimit) { entry.trys++; entry.time = time; return true; } - if(entry.time + banMillis < time) + if(entry.time + rateLimitMillis < time) { entry.trys = 1; entry.time = 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 97fcc40f..5b3346c3 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/components/AuthLimiterComponent.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/components/AuthLimiterComponent.java @@ -9,9 +9,7 @@ import pro.gravit.launchserver.socket.response.auth.AuthResponse; import pro.gravit.utils.HookException; -public class AuthLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable { - - private transient AbstractLimiter limiter; +public class AuthLimiterComponent extends AbstractLimiter implements NeedGarbageCollection, AutoCloseable { private transient LaunchServer srv; @Override public void preInit(LaunchServer launchServer) { @@ -20,7 +18,6 @@ public void preInit(LaunchServer launchServer) { @Override public void init(LaunchServer launchServer) { - limiter = new AbstractLimiter<>(rateLimit, rateLimitMilis); launchServer.authHookManager.preHook.registerHook(this::preAuthHook); } @@ -30,22 +27,12 @@ public void postInit(LaunchServer launchServer) { } public boolean preAuthHook(AuthResponse.AuthContext context, Client client) { - if (!excludeIps.contains(context.ip) && !limiter.check(context.ip)) { + if (!check(context.ip)) { throw new HookException(message); } return false; } - - public int rateLimit; - public int rateLimitMilis; public String message; - public List excludeIps = new ArrayList<>(); - - @Override - public void garbageCollection() { - if(limiter != null) - limiter.garbageCollection(); - } @Override public void close() throws Exception { 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 a268c9a0..8a6327cd 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/components/RegLimiterComponent.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/components/RegLimiterComponent.java @@ -8,19 +8,15 @@ import pro.gravit.launchserver.manangers.hook.AuthHookManager; import pro.gravit.utils.HookException; -public class RegLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable { +public class RegLimiterComponent extends AbstractLimiter implements NeedGarbageCollection, AutoCloseable { - private transient AbstractLimiter limiter; public transient LaunchServer launchServer; - public int rateLimit; - public int rateLimitMilis; public String message; public List excludeIps = new ArrayList<>(); @Override public void preInit(LaunchServer launchServer) { - limiter = new AbstractLimiter<>(rateLimit, rateLimitMilis); this.launchServer = launchServer; } @@ -36,17 +32,12 @@ public void postInit(LaunchServer launchServer) { public boolean registerHook(AuthHookManager.RegContext context) { - if (!limiter.check(context.ip)) { + if (!check(context.ip)) { throw new HookException(message); } return false; } - @Override - public void garbageCollection() { - if(limiter != null) - limiter.garbageCollection(); - } @Override public void close() throws Exception { launchServer.authHookManager.registraion.unregisterHook(this::registerHook);