[FIX][FEATURE] Начальная переработка иницализации лаунчсервера. Фикс инициализации компонентов

This commit is contained in:
Gravit 2019-08-25 13:48:26 +07:00
parent a30c1db986
commit 82e3ae797c
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
4 changed files with 109 additions and 64 deletions

View file

@ -91,16 +91,38 @@
public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurable { public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurable {
public void reload() throws Exception { public enum ReloadType
config.close(); {
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"); LogHelper.info("Reading LaunchServer config file");
try (BufferedReader reader = IOHelper.newReader(configFile)) { try (BufferedReader reader = IOHelper.newReader(configFile)) {
config = Launcher.gsonManager.gson.fromJson(reader, Config.class); config = Launcher.gsonManager.gson.fromJson(reader, Config.class);
} }
config.server = this; config.server = this;
if(type.equals(ReloadType.NO_AUTH))
{
config.auth = pairs;
}
config.verify(); config.verify();
config.init(); config.init(type);
if (config.components != null) { 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"); LogHelper.debug("Init components");
config.components.forEach((k, v) -> { config.components.forEach((k, v) -> {
LogHelper.subDebug("Init component %s", k); LogHelper.subDebug("Init component %s", k);
@ -124,7 +146,26 @@ public Map<String, Command> getCommands() {
SubCommand reload = new SubCommand() { SubCommand reload = new SubCommand() {
@Override @Override
public void invoke(String... args) throws Exception { 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); commands.put("reload", reload);
@ -229,7 +270,7 @@ public void verify() {
} }
} }
public void init() { public void init(ReloadType type) {
Launcher.applyLauncherEnv(env); Launcher.applyLauncherEnv(env);
for (AuthProviderPair provider : auth) { for (AuthProviderPair provider : auth) {
provider.init(server); provider.init(server);
@ -241,34 +282,53 @@ public void init() {
if (protectHandler != null) { if (protectHandler != null) {
protectHandler.checkLaunchServerLicense(); protectHandler.checkLaunchServerLicense();
} }
if (components != null) { if(components != null)
LogHelper.debug("PreInit components"); {
components.forEach((k, v) -> { components.forEach((k,v) -> {
LogHelper.subDebug("PreInit component %s", k); server.registerObject("component.".concat(k), v);
v.preInit(server);
}); });
LogHelper.debug("PreInit components successful");
} }
server.registerObject("permissionsHandler", permissionsHandler); server.registerObject("permissionsHandler", permissionsHandler);
server.registerObject("hwidHandler", hwidHandler); server.registerObject("hwidHandler", hwidHandler);
for (int i = 0; i < auth.length; ++i) { if(!type.equals(ReloadType.NO_AUTH))
AuthProviderPair pair = auth[i]; {
server.registerObject("auth.".concat(pair.name).concat(".provider"), pair.provider); for (int i = 0; i < auth.length; ++i) {
server.registerObject("auth.".concat(pair.name).concat(".handler"), pair.handler); AuthProviderPair pair = auth[i];
server.registerObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider); 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); Arrays.stream(mirrors).forEach(server.mirrorManager::addMirror);
} }
public void close() { public void close(ReloadType type) {
try { try {
server.unregisterObject("permissionsHandler", permissionsHandler); server.unregisterObject("permissionsHandler", permissionsHandler);
server.unregisterObject("hwidHandler", hwidHandler); server.unregisterObject("hwidHandler", hwidHandler);
for (AuthProviderPair pair : auth) { if(!type.equals(ReloadType.NO_AUTH))
server.unregisterObject("auth.".concat(pair.name).concat(".provider"), pair.provider); {
server.unregisterObject("auth.".concat(pair.name).concat(".handler"), pair.handler); for (AuthProviderPair pair : auth) {
server.unregisterObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider); 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) { } catch (Exception e) {
LogHelper.error(e); LogHelper.error(e);
@ -618,6 +678,14 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
} }
runtime.verify(); runtime.verify();
config.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 // build hooks, anti-brutforce and other
buildHookManager = new BuildHookManager(); 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); registerObject("launchServer", this);
GarbageManager.registerNeedGC(sessionManager); GarbageManager.registerNeedGC(sessionManager);
@ -763,7 +831,7 @@ public void buildLauncherBinaries() throws IOException {
public void close() { public void close() {
// Close handlers & providers // Close handlers & providers
config.close(); config.close(ReloadType.FULL);
modulesManager.close(); modulesManager.close();
LogHelper.info("Save LaunchServer runtime config"); LogHelper.info("Save LaunchServer runtime config");
try (Writer writer = IOHelper.newWriter(runtimeConfigFile)) { try (Writer writer = IOHelper.newWriter(runtimeConfigFile)) {
@ -838,12 +906,12 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
newConfig.components = new HashMap<>(); newConfig.components = new HashMap<>();
AuthLimiterComponent authLimiterComponent = new AuthLimiterComponent(); AuthLimiterComponent authLimiterComponent = new AuthLimiterComponent();
authLimiterComponent.rateLimit = 3; authLimiterComponent.rateLimit = 3;
authLimiterComponent.rateLimitMilis = 8000; authLimiterComponent.rateLimitMillis = 8000;
authLimiterComponent.message = "Превышен лимит авторизаций"; authLimiterComponent.message = "Превышен лимит авторизаций";
newConfig.components.put("authLimiter", authLimiterComponent); newConfig.components.put("authLimiter", authLimiterComponent);
RegLimiterComponent regLimiterComponent = new RegLimiterComponent(); RegLimiterComponent regLimiterComponent = new RegLimiterComponent();
regLimiterComponent.rateLimit = 3; regLimiterComponent.rateLimit = 3;
regLimiterComponent.rateLimitMilis = 1000 * 60 * 60 * 10; //Блок на 10 часов regLimiterComponent.rateLimitMillis = 1000 * 60 * 60 * 10; //Блок на 10 часов
regLimiterComponent.message = "Превышен лимит регистраций"; regLimiterComponent.message = "Превышен лимит регистраций";
newConfig.components.put("regLimiter", regLimiterComponent); newConfig.components.put("regLimiter", regLimiterComponent);

View file

@ -1,23 +1,21 @@
package pro.gravit.launchserver.components; package pro.gravit.launchserver.components;
import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Map; import java.util.Map;
import pro.gravit.launcher.NeedGarbageCollection; import pro.gravit.launcher.NeedGarbageCollection;
public class AbstractLimiter<T> implements NeedGarbageCollection { public abstract class AbstractLimiter<T> extends Component implements NeedGarbageCollection {
public final int maxTrys; public int rateLimit;
public final int banMillis; public int rateLimitMillis;
public List<T> exclude = new ArrayList<>();
public AbstractLimiter(int maxTrys, int banMillis) {
this.maxTrys = maxTrys;
this.banMillis = banMillis;
}
@Override @Override
public void garbageCollection() { public void garbageCollection() {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
map.entrySet().removeIf((e) -> e.getValue().time + banMillis < time); map.entrySet().removeIf((e) -> e.getValue().time + rateLimitMillis < time);
} }
class LimitEntry class LimitEntry
@ -35,9 +33,10 @@ public LimitEntry() {
trys = 0; trys = 0;
} }
} }
protected Map<T, LimitEntry> map = new HashMap<>(); protected transient Map<T, LimitEntry> map = new HashMap<>();
public boolean check(T address) public boolean check(T address)
{ {
if(exclude.contains(address)) return true;
LimitEntry entry = map.get(address); LimitEntry entry = map.get(address);
if(entry == null) if(entry == null)
{ {
@ -47,13 +46,13 @@ public boolean check(T address)
else else
{ {
long time = System.currentTimeMillis(); long time = System.currentTimeMillis();
if(entry.trys < maxTrys) if(entry.trys < rateLimit)
{ {
entry.trys++; entry.trys++;
entry.time = time; entry.time = time;
return true; return true;
} }
if(entry.time + banMillis < time) if(entry.time + rateLimitMillis < time)
{ {
entry.trys = 1; entry.trys = 1;
entry.time = time; entry.time = time;

View file

@ -9,9 +9,7 @@
import pro.gravit.launchserver.socket.response.auth.AuthResponse; import pro.gravit.launchserver.socket.response.auth.AuthResponse;
import pro.gravit.utils.HookException; import pro.gravit.utils.HookException;
public class AuthLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable { public class AuthLimiterComponent extends AbstractLimiter<String> implements NeedGarbageCollection, AutoCloseable {
private transient AbstractLimiter<String> limiter;
private transient LaunchServer srv; private transient LaunchServer srv;
@Override @Override
public void preInit(LaunchServer launchServer) { public void preInit(LaunchServer launchServer) {
@ -20,7 +18,6 @@ public void preInit(LaunchServer launchServer) {
@Override @Override
public void init(LaunchServer launchServer) { public void init(LaunchServer launchServer) {
limiter = new AbstractLimiter<>(rateLimit, rateLimitMilis);
launchServer.authHookManager.preHook.registerHook(this::preAuthHook); launchServer.authHookManager.preHook.registerHook(this::preAuthHook);
} }
@ -30,22 +27,12 @@ public void postInit(LaunchServer launchServer) {
} }
public boolean preAuthHook(AuthResponse.AuthContext context, Client client) { 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); throw new HookException(message);
} }
return false; return false;
} }
public int rateLimit;
public int rateLimitMilis;
public String message; public String message;
public List<String> excludeIps = new ArrayList<>();
@Override
public void garbageCollection() {
if(limiter != null)
limiter.garbageCollection();
}
@Override @Override
public void close() throws Exception { public void close() throws Exception {

View file

@ -8,19 +8,15 @@
import pro.gravit.launchserver.manangers.hook.AuthHookManager; import pro.gravit.launchserver.manangers.hook.AuthHookManager;
import pro.gravit.utils.HookException; import pro.gravit.utils.HookException;
public class RegLimiterComponent extends Component implements NeedGarbageCollection, AutoCloseable { public class RegLimiterComponent extends AbstractLimiter<String> implements NeedGarbageCollection, AutoCloseable {
private transient AbstractLimiter<String> limiter;
public transient LaunchServer launchServer; public transient LaunchServer launchServer;
public int rateLimit;
public int rateLimitMilis;
public String message; public String message;
public List<String> excludeIps = new ArrayList<>(); public List<String> excludeIps = new ArrayList<>();
@Override @Override
public void preInit(LaunchServer launchServer) { public void preInit(LaunchServer launchServer) {
limiter = new AbstractLimiter<>(rateLimit, rateLimitMilis);
this.launchServer = launchServer; this.launchServer = launchServer;
} }
@ -36,17 +32,12 @@ public void postInit(LaunchServer launchServer) {
public boolean registerHook(AuthHookManager.RegContext context) public boolean registerHook(AuthHookManager.RegContext context)
{ {
if (!limiter.check(context.ip)) { if (!check(context.ip)) {
throw new HookException(message); throw new HookException(message);
} }
return false; return false;
} }
@Override
public void garbageCollection() {
if(limiter != null)
limiter.garbageCollection();
}
@Override @Override
public void close() throws Exception { public void close() throws Exception {
launchServer.authHookManager.registraion.unregisterHook(this::registerHook); launchServer.authHookManager.registraion.unregisterHook(this::registerHook);