[FEATURE] Большая фитча - переход на LaunchServerBuilder

This commit is contained in:
Gravit 2019-08-25 16:39:08 +07:00
parent 12388226f5
commit 867ae334fa
No known key found for this signature in database
GPG key ID: 061981E1E85D3216
9 changed files with 409 additions and 234 deletions

View file

@ -1,4 +1,4 @@
def mainClassName = "pro.gravit.launchserver.LaunchServer" def mainClassName = "pro.gravit.launchserver.LaunchServerStarter"
def mainAgentName = "pro.gravit.launchserver.StarterAgent" def mainAgentName = "pro.gravit.launchserver.StarterAgent"
evaluationDependsOn(':Launcher') evaluationDependsOn(':Launcher')

View file

@ -1,10 +1,7 @@
package pro.gravit.launchserver; package pro.gravit.launchserver;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.io.Writer;
import java.lang.ProcessBuilder.Redirect; import java.lang.ProcessBuilder.Redirect;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.nio.file.DirectoryStream; import java.nio.file.DirectoryStream;
@ -33,62 +30,33 @@
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
import java.util.zip.CRC32; import java.util.zip.CRC32;
import io.netty.channel.epoll.Epoll;
import org.bouncycastle.crypto.util.PrivateKeyFactory; import org.bouncycastle.crypto.util.PrivateKeyFactory;
import org.bouncycastle.operator.OperatorCreationException; import org.bouncycastle.operator.OperatorCreationException;
import io.netty.handler.logging.LogLevel;
import pro.gravit.launcher.Launcher; import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.LauncherConfig;
import pro.gravit.launcher.NeedGarbageCollection; import pro.gravit.launcher.NeedGarbageCollection;
import pro.gravit.launcher.hasher.HashedDir; import pro.gravit.launcher.hasher.HashedDir;
import pro.gravit.launcher.hwid.HWIDProvider;
import pro.gravit.launcher.managers.ConfigManager; import pro.gravit.launcher.managers.ConfigManager;
import pro.gravit.launcher.managers.GarbageManager; import pro.gravit.launcher.managers.GarbageManager;
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launchserver.auth.AuthProviderPair; import pro.gravit.launchserver.auth.AuthProviderPair;
import pro.gravit.launchserver.auth.handler.AuthHandler;
import pro.gravit.launchserver.auth.handler.MemoryAuthHandler;
import pro.gravit.launchserver.auth.hwid.AcceptHWIDHandler;
import pro.gravit.launchserver.auth.hwid.HWIDHandler;
import pro.gravit.launchserver.auth.permissions.DefaultPermissionsHandler;
import pro.gravit.launchserver.auth.permissions.JsonFilePermissionsHandler;
import pro.gravit.launchserver.auth.permissions.PermissionsHandler;
import pro.gravit.launchserver.auth.protect.ProtectHandler;
import pro.gravit.launchserver.auth.protect.StdProtectHandler;
import pro.gravit.launchserver.auth.provider.AuthProvider;
import pro.gravit.launchserver.auth.provider.RejectAuthProvider;
import pro.gravit.launchserver.auth.texture.RequestTextureProvider;
import pro.gravit.launchserver.auth.texture.TextureProvider;
import pro.gravit.launchserver.binary.EXEL4JLauncherBinary; import pro.gravit.launchserver.binary.EXEL4JLauncherBinary;
import pro.gravit.launchserver.binary.EXELauncherBinary; import pro.gravit.launchserver.binary.EXELauncherBinary;
import pro.gravit.launchserver.binary.JARLauncherBinary; import pro.gravit.launchserver.binary.JARLauncherBinary;
import pro.gravit.launchserver.binary.LauncherBinary; import pro.gravit.launchserver.binary.LauncherBinary;
import pro.gravit.launchserver.binary.ProguardConf; import pro.gravit.launchserver.binary.ProguardConf;
import pro.gravit.launchserver.binary.SimpleEXELauncherBinary; import pro.gravit.launchserver.binary.SimpleEXELauncherBinary;
import pro.gravit.launchserver.components.AuthLimiterComponent;
import pro.gravit.launchserver.components.Component;
import pro.gravit.launchserver.components.RegLimiterComponent;
import pro.gravit.launchserver.config.LaunchServerConfig; import pro.gravit.launchserver.config.LaunchServerConfig;
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig; import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
import pro.gravit.launchserver.dao.provider.DaoProvider; import pro.gravit.launchserver.manangers.*;
import pro.gravit.launchserver.manangers.CertificateManager;
import pro.gravit.launchserver.manangers.LaunchServerGsonManager;
import pro.gravit.launchserver.manangers.MirrorManager;
import pro.gravit.launchserver.manangers.ModulesManager;
import pro.gravit.launchserver.manangers.ReconfigurableManager;
import pro.gravit.launchserver.manangers.SessionManager;
import pro.gravit.launchserver.manangers.hook.AuthHookManager; import pro.gravit.launchserver.manangers.hook.AuthHookManager;
import pro.gravit.launchserver.manangers.hook.BuildHookManager; import pro.gravit.launchserver.manangers.hook.BuildHookManager;
import pro.gravit.launchserver.socket.WebSocketService;
import pro.gravit.launchserver.socket.handlers.NettyServerSocketHandler; import pro.gravit.launchserver.socket.handlers.NettyServerSocketHandler;
import pro.gravit.utils.Version;
import pro.gravit.utils.command.*; import pro.gravit.utils.command.*;
import pro.gravit.utils.helper.CommonHelper; import pro.gravit.utils.helper.CommonHelper;
import pro.gravit.utils.helper.IOHelper; import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.JVMHelper; import pro.gravit.utils.helper.JVMHelper;
import pro.gravit.utils.helper.LogHelper; import pro.gravit.utils.helper.LogHelper;
import pro.gravit.utils.helper.SecurityHelper;
public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurable { public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurable {
@ -98,6 +66,20 @@ public enum ReloadType
NO_COMPONENTS, NO_COMPONENTS,
FULL FULL
} }
public enum LaunchServerEnv
{
TEST,
DEV,
DEBUG,
PRODUCTION
}
public interface LaunchServerConfigManager
{
LaunchServerConfig readConfig() throws IOException;
LaunchServerRuntimeConfig readRuntimeConfig() throws IOException;
void writeConfig(LaunchServerConfig config) throws IOException;
void writeRuntimeConfig(LaunchServerRuntimeConfig config) throws IOException;
}
public void reload(ReloadType type) throws Exception { public void reload(ReloadType type) throws Exception {
config.close(type); config.close(type);
@ -107,9 +89,7 @@ public void reload(ReloadType type) throws Exception {
pairs = config.auth; pairs = config.auth;
} }
LogHelper.info("Reading LaunchServer config file"); LogHelper.info("Reading LaunchServer config file");
try (BufferedReader reader = IOHelper.newReader(configFile)) { config = launchServerConfigManager.readConfig();
config = Launcher.gsonManager.gson.fromJson(reader, LaunchServerConfig.class);
}
config.setLaunchServer(this); config.setLaunchServer(this);
if(type.equals(ReloadType.NO_AUTH)) if(type.equals(ReloadType.NO_AUTH))
{ {
@ -198,53 +178,16 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
} }
} }
public static void main(String... args) throws Throwable {
JVMHelper.checkStackTrace(LaunchServer.class);
JVMHelper.verifySystemProperties(LaunchServer.class, true);
LogHelper.addOutput(IOHelper.WORKING_DIR.resolve("LaunchServer.log"));
LogHelper.printVersion("LaunchServer");
LogHelper.printLicense("LaunchServer");
if (!StarterAgent.isAgentStarted()) {
LogHelper.error("StarterAgent is not started!");
LogHelper.error("You should add to JVM options this option: `-javaagent:LaunchServer.jar`");
}
// Start LaunchServer
long startTime = System.currentTimeMillis();
try {
@SuppressWarnings("resource")
LaunchServer launchserver = new LaunchServer(IOHelper.WORKING_DIR, false, args);
if (args.length == 0) launchserver.run();
else { //Обработка команды
launchserver.commandHandler.eval(args, false);
}
} catch (Throwable exc) {
LogHelper.error(exc);
return;
}
long endTime = System.currentTimeMillis();
LogHelper.debug("LaunchServer started in %dms", endTime - startTime);
}
// Constant paths // Constant paths
public final Path dir; public final Path dir;
public final boolean testEnv; public final LaunchServerEnv env;
public final Path launcherLibraries; public final Path launcherLibraries;
public final Path launcherLibrariesCompile; public final Path launcherLibrariesCompile;
public final List<String> args;
public final Path configFile;
public final Path runtimeConfigFile;
public final Path publicKeyFile;
public final Path privateKeyFile;
public final Path caCertFile; public final Path caCertFile;
public final Path caKeyFile; public final Path caKeyFile;
@ -255,6 +198,8 @@ public static void main(String... args) throws Throwable {
public final Path updatesDir; public final Path updatesDir;
public final LaunchServerConfigManager launchServerConfigManager;
//public static LaunchServer server = null; //public static LaunchServer server = null;
public final Path profilesDir; public final Path profilesDir;
@ -311,33 +256,35 @@ public static void main(String... args) throws Throwable {
public static Class<? extends LauncherBinary> defaultLauncherEXEBinaryClass = null; public static Class<? extends LauncherBinary> defaultLauncherEXEBinaryClass = null;
public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException, InvalidKeySpecException { public static class LaunchServerDirectories
this.dir = dir; {
this.testEnv = testEnv; public Path updatesDir;
public Path profilesDir;
public Path dir;
public void collect()
{
if(updatesDir == null) updatesDir = dir.resolve("updates");
if(profilesDir == null) profilesDir = dir.resolve("profiles");
}
}
public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, ModulesManager modulesManager, RSAPublicKey publicKey, RSAPrivateKey privateKey, CommandHandler commandHandler) throws IOException, InvalidKeySpecException {
this.dir = directories.dir;
this.env = env;
this.config = config;
this.launchServerConfigManager = launchServerConfigManager;
this.modulesManager = modulesManager;
this.profilesDir = directories.profilesDir;
this.updatesDir = directories.updatesDir;
this.publicKey = publicKey;
this.privateKey = privateKey;
this.commandHandler = commandHandler;
this.runtime = runtimeConfig;
taskPool = new Timer("Timered task worker thread", true); taskPool = new Timer("Timered task worker thread", true);
launcherLibraries = dir.resolve("launcher-libraries"); launcherLibraries = dir.resolve("launcher-libraries");
launcherLibrariesCompile = dir.resolve("launcher-libraries-compile"); launcherLibrariesCompile = dir.resolve("launcher-libraries-compile");
this.args = Arrays.asList(args);
if(IOHelper.exists(dir.resolve("LaunchServer.conf"))) config.setLaunchServer(this);
{
configFile = dir.resolve("LaunchServer.conf");
}
else
{
configFile = dir.resolve("LaunchServer.json");
}
if(IOHelper.exists(dir.resolve("RuntimeLaunchServer.conf")))
{
runtimeConfigFile = dir.resolve("RuntimeLaunchServer.conf");
}
else
{
runtimeConfigFile = dir.resolve("RuntimeLaunchServer.json");
}
publicKeyFile = dir.resolve("public.key");
privateKeyFile = dir.resolve("private.key");
updatesDir = dir.resolve("updates");
profilesDir = dir.resolve("profiles");
caCertFile = dir.resolve("ca.crt"); caCertFile = dir.resolve("ca.crt");
caKeyFile = dir.resolve("ca.key"); caKeyFile = dir.resolve("ca.key");
@ -345,54 +292,7 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
serverCertFile = dir.resolve("server.crt"); serverCertFile = dir.resolve("server.crt");
serverKeyFile = dir.resolve("server.key"); serverKeyFile = dir.resolve("server.key");
//Registration handlers and providers modulesManager.initContext(this);
AuthHandler.registerHandlers();
AuthProvider.registerProviders();
TextureProvider.registerProviders();
HWIDHandler.registerHandlers();
PermissionsHandler.registerHandlers();
Component.registerComponents();
ProtectHandler.registerHandlers();
WebSocketService.registerResponses();
HWIDProvider.registerHWIDs();
DaoProvider.registerProviders();
//LaunchServer.server = this;
// Set command handler
CommandHandler localCommandHandler;
if (testEnv)
localCommandHandler = new StdCommandHandler(false);
else
try {
Class.forName("org.jline.terminal.Terminal");
// JLine2 available
localCommandHandler = new JLineCommandHandler();
LogHelper.info("JLine2 terminal enabled");
} catch (ClassNotFoundException ignored) {
localCommandHandler = new StdCommandHandler(true);
LogHelper.warning("JLine2 isn't in classpath, using std");
}
commandHandler = localCommandHandler;
// Set key pair
if (IOHelper.isFile(publicKeyFile) && IOHelper.isFile(privateKeyFile)) {
LogHelper.info("Reading RSA keypair");
publicKey = SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile));
privateKey = SecurityHelper.toPrivateRSAKey(IOHelper.read(privateKeyFile));
if (!publicKey.getModulus().equals(privateKey.getModulus()))
throw new IOException("Private and public key modulus mismatch");
} else {
LogHelper.info("Generating RSA keypair");
KeyPair pair = SecurityHelper.genRSAKeyPair();
publicKey = (RSAPublicKey) pair.getPublic();
privateKey = (RSAPrivateKey) pair.getPrivate();
// Write key pair list
LogHelper.info("Writing RSA keypair list");
IOHelper.write(publicKeyFile, publicKey.getEncoded());
IOHelper.write(privateKeyFile, privateKey.getEncoded());
}
// Print keypair fingerprints // Print keypair fingerprints
CRC32 crc = new CRC32(); CRC32 crc = new CRC32();
@ -403,28 +303,10 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
launcherEXEBinaryClass = defaultLauncherEXEBinaryClass; launcherEXEBinaryClass = defaultLauncherEXEBinaryClass;
// pre init modules // pre init modules
modulesManager = new ModulesManager(this); //modulesManager = new ModulesManager(this);
modulesManager.autoload(dir.resolve("modules")); //modulesManager.autoload(dir.resolve("modules"));
modulesManager.preInitModules(); modulesManager.preInitModules();
initGson();
// Read LaunchServer config
generateConfigIfNotExists(testEnv);
LogHelper.info("Reading LaunchServer config file");
try (BufferedReader reader = IOHelper.newReader(configFile)) {
config = Launcher.gsonManager.gson.fromJson(reader, LaunchServerConfig.class);
}
config.setLaunchServer(this);
if (!Files.exists(runtimeConfigFile)) {
LogHelper.info("Reset LaunchServer runtime config file");
runtime = new LaunchServerRuntimeConfig();
runtime.reset();
} else {
LogHelper.info("Reading LaunchServer runtime config file");
try (BufferedReader reader = IOHelper.newReader(runtimeConfigFile)) {
runtime = Launcher.gsonManager.gson.fromJson(reader, LaunchServerRuntimeConfig.class);
}
}
runtime.verify(); runtime.verify();
config.verify(); config.verify();
if (config.components != null) { if (config.components != null) {
@ -486,7 +368,7 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
registerObject("launchServer", this); registerObject("launchServer", this);
GarbageManager.registerNeedGC(sessionManager); GarbageManager.registerNeedGC(sessionManager);
pro.gravit.launchserver.command.handler.CommandHandler.registerCommands(localCommandHandler, this); pro.gravit.launchserver.command.handler.CommandHandler.registerCommands(commandHandler, this);
// init modules // init modules
modulesManager.initModules(); modulesManager.initModules();
@ -534,11 +416,6 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
nettyServerSocketHandler = null; nettyServerSocketHandler = null;
} }
public static void initGson() {
Launcher.gsonManager = new LaunchServerGsonManager();
Launcher.gsonManager.initGson();
}
private LauncherBinary binary() { private LauncherBinary binary() {
if (launcherEXEBinaryClass != null) { if (launcherEXEBinaryClass != null) {
try { try {
@ -576,66 +453,17 @@ public void buildLauncherBinaries() throws IOException {
launcherEXEBinary.build(); launcherEXEBinary.build();
} }
public void close() { public void close() throws Exception {
// Close handlers & providers // Close handlers & providers
config.close(ReloadType.FULL); 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)) { launchServerConfigManager.writeRuntimeConfig(runtime);
if (Launcher.gsonManager.configGson != null) {
Launcher.gsonManager.configGson.toJson(runtime, writer);
} else {
LogHelper.error("Error writing LaunchServer runtime config file. Gson is null");
}
} catch (IOException e) {
LogHelper.error(e);
}
// Print last message before death :( // Print last message before death :(
LogHelper.info("LaunchServer stopped"); LogHelper.info("LaunchServer stopped");
} }
private void generateConfigIfNotExists(boolean testEnv) throws IOException {
if (IOHelper.isFile(configFile))
return;
// Create new config
LogHelper.info("Creating LaunchServer config");
LaunchServerConfig newConfig = LaunchServerConfig.getDefault();
// Set server address
String address;
if (testEnv) {
address = "localhost";
newConfig.setProjectName("test");
} else {
System.out.println("LaunchServer address(default: localhost): ");
address = commandHandler.readLine();
System.out.println("LaunchServer projectName: ");
newConfig.setProjectName(commandHandler.readLine());
}
if (address == null || address.isEmpty()) {
LogHelper.error("Address null. Using localhost");
address = "localhost";
}
if (newConfig.projectName == null || newConfig.projectName.isEmpty()) {
LogHelper.error("ProjectName null. Using MineCraft");
newConfig.projectName = "MineCraft";
}
newConfig.netty.address = "ws://" + address + ":9274/api";
newConfig.netty.downloadURL = "http://" + address + ":9274/%dirname%/";
newConfig.netty.launcherURL = "http://" + address + ":9274/Launcher.jar";
newConfig.netty.launcherEXEURL = "http://" + address + ":9274/Launcher.exe";
// Write LaunchServer config
LogHelper.info("Writing LaunchServer config file");
try (BufferedWriter writer = IOHelper.newWriter(configFile)) {
Launcher.gsonManager.configGson.toJson(newConfig, writer);
}
}
public List<ClientProfile> getProfiles() { public List<ClientProfile> getProfiles() {
return profilesList; return profilesList;
} }
@ -664,8 +492,14 @@ public void run() {
throw new IllegalStateException("LaunchServer has been already started"); throw new IllegalStateException("LaunchServer has been already started");
// Add shutdown hook, then start LaunchServer // Add shutdown hook, then start LaunchServer
if (!this.testEnv) { if (!this.env.equals(LaunchServerEnv.TEST)) {
JVMHelper.RUNTIME.addShutdownHook(CommonHelper.newThread(null, false, this::close)); JVMHelper.RUNTIME.addShutdownHook(CommonHelper.newThread(null, false, () -> {
try {
close();
} catch (Exception e) {
LogHelper.error(e);
}
}));
CommonHelper.newThread("Command Thread", true, commandHandler).start(); CommonHelper.newThread("Command Thread", true, commandHandler).start();
} }
if (config.netty != null) if (config.netty != null)

View file

@ -0,0 +1,104 @@
package pro.gravit.launchserver;
import pro.gravit.launchserver.config.LaunchServerConfig;
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
import pro.gravit.launchserver.manangers.ModulesManager;
import pro.gravit.utils.command.CommandHandler;
import java.nio.file.Path;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
public class LaunchServerBuilder {
private LaunchServerConfig config;
private LaunchServerRuntimeConfig runtimeConfig;
private CommandHandler commandHandler;
private LaunchServer.LaunchServerEnv env;
private ModulesManager modulesManager;
private LaunchServer.LaunchServerDirectories directories = new LaunchServer.LaunchServerDirectories();
private RSAPublicKey publicKey;
private RSAPrivateKey privateKey;
private LaunchServer.LaunchServerConfigManager launchServerConfigManager;
public LaunchServerBuilder setConfig(LaunchServerConfig config) {
this.config = config;
return this;
}
public LaunchServerBuilder setEnv(LaunchServer.LaunchServerEnv env) {
this.env = env;
return this;
}
public LaunchServerBuilder setModulesManager(ModulesManager modulesManager) {
this.modulesManager = modulesManager;
return this;
}
public LaunchServerBuilder setRuntimeConfig(LaunchServerRuntimeConfig runtimeConfig) {
this.runtimeConfig = runtimeConfig;
return this;
}
public LaunchServerBuilder setCommandHandler(CommandHandler commandHandler) {
this.commandHandler = commandHandler;
return this;
}
public LaunchServerBuilder setDirectories(LaunchServer.LaunchServerDirectories directories) {
this.directories = directories;
return this;
}
public LaunchServerBuilder setDir(Path dir) {
this.directories.dir = dir;
return this;
}
public LaunchServerBuilder setPublicKey(RSAPublicKey publicKey) {
this.publicKey = publicKey;
return this;
}
public LaunchServerBuilder setPrivateKey(RSAPrivateKey privateKey) {
this.privateKey = privateKey;
return this;
}
public LaunchServerBuilder setLaunchServerConfigManager(LaunchServer.LaunchServerConfigManager launchServerConfigManager) {
this.launchServerConfigManager = launchServerConfigManager;
return this;
}
public LaunchServer build() throws Exception
{
//if(updatesDir == null) updatesDir = dir.resolve("updates");
//if(profilesDir == null) profilesDir = dir.resolve("profiles");
directories.collect();
if(launchServerConfigManager == null)
{
launchServerConfigManager = new LaunchServer.LaunchServerConfigManager() {
@Override
public LaunchServerConfig readConfig() {
throw new UnsupportedOperationException();
}
@Override
public LaunchServerRuntimeConfig readRuntimeConfig() {
throw new UnsupportedOperationException();
}
@Override
public void writeConfig(LaunchServerConfig config) {
throw new UnsupportedOperationException();
}
@Override
public void writeRuntimeConfig(LaunchServerRuntimeConfig config) {
throw new UnsupportedOperationException();
}
};
}
return new LaunchServer(directories, env, config, runtimeConfig, launchServerConfigManager, modulesManager, publicKey, privateKey, commandHandler);
}
}

View file

@ -0,0 +1,232 @@
package pro.gravit.launchserver;
import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.hwid.HWIDProvider;
import pro.gravit.launchserver.auth.handler.AuthHandler;
import pro.gravit.launchserver.auth.hwid.HWIDHandler;
import pro.gravit.launchserver.auth.permissions.PermissionsHandler;
import pro.gravit.launchserver.auth.protect.ProtectHandler;
import pro.gravit.launchserver.auth.provider.AuthProvider;
import pro.gravit.launchserver.auth.texture.TextureProvider;
import pro.gravit.launchserver.components.Component;
import pro.gravit.launchserver.config.LaunchServerConfig;
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
import pro.gravit.launchserver.dao.provider.DaoProvider;
import pro.gravit.launchserver.manangers.LaunchServerGsonManager;
import pro.gravit.launchserver.manangers.ModulesManager;
import pro.gravit.launchserver.socket.WebSocketService;
import pro.gravit.utils.command.CommandHandler;
import pro.gravit.utils.command.JLineCommandHandler;
import pro.gravit.utils.command.StdCommandHandler;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.JVMHelper;
import pro.gravit.utils.helper.LogHelper;
import pro.gravit.utils.helper.SecurityHelper;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.security.KeyPair;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
public class LaunchServerStarter {
public static void main(String[] args) throws Exception {
JVMHelper.checkStackTrace(LaunchServerStarter.class);
JVMHelper.verifySystemProperties(LaunchServer.class, true);
LogHelper.addOutput(IOHelper.WORKING_DIR.resolve("LaunchServer.log"));
LogHelper.printVersion("LaunchServer");
LogHelper.printLicense("LaunchServer");
if (!StarterAgent.isAgentStarted()) {
LogHelper.error("StarterAgent is not started!");
LogHelper.error("You should add to JVM options this option: `-javaagent:LaunchServer.jar`");
}
Path dir = IOHelper.WORKING_DIR;
Path configFile, runtimeConfigFile;
Path publicKeyFile =dir.resolve("public.key");
Path privateKeyFile = dir.resolve("private.key");
RSAPublicKey publicKey;
RSAPrivateKey privateKey;
LaunchServerRuntimeConfig runtimeConfig;
LaunchServerConfig config;
LaunchServer.LaunchServerEnv env = LaunchServer.LaunchServerEnv.PRODUCTION;
ModulesManager modulesManager = new ModulesManager(dir.resolve("config"));
modulesManager.autoload(dir.resolve("modules"));
registerAll();
initGson();
if (IOHelper.exists(dir.resolve("LaunchServer.conf"))) {
configFile = dir.resolve("LaunchServer.conf");
} else {
configFile = dir.resolve("LaunchServer.json");
}
if (IOHelper.exists(dir.resolve("RuntimeLaunchServer.conf"))) {
runtimeConfigFile = dir.resolve("RuntimeLaunchServer.conf");
} else {
runtimeConfigFile = dir.resolve("RuntimeLaunchServer.json");
}
CommandHandler localCommandHandler;
try {
Class.forName("org.jline.terminal.Terminal");
// JLine2 available
localCommandHandler = new JLineCommandHandler();
LogHelper.info("JLine2 terminal enabled");
} catch (ClassNotFoundException ignored) {
localCommandHandler = new StdCommandHandler(true);
LogHelper.warning("JLine2 isn't in classpath, using std");
}
if (IOHelper.isFile(publicKeyFile) && IOHelper.isFile(privateKeyFile)) {
LogHelper.info("Reading RSA keypair");
publicKey = SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile));
privateKey = SecurityHelper.toPrivateRSAKey(IOHelper.read(privateKeyFile));
if (!publicKey.getModulus().equals(privateKey.getModulus()))
throw new IOException("Private and public key modulus mismatch");
} else {
LogHelper.info("Generating RSA keypair");
KeyPair pair = SecurityHelper.genRSAKeyPair();
publicKey = (RSAPublicKey) pair.getPublic();
privateKey = (RSAPrivateKey) pair.getPrivate();
// Write key pair list
LogHelper.info("Writing RSA keypair list");
IOHelper.write(publicKeyFile, publicKey.getEncoded());
IOHelper.write(privateKeyFile, privateKey.getEncoded());
}
if (!Files.exists(runtimeConfigFile)) {
LogHelper.info("Reset LaunchServer runtime config file");
runtimeConfig = new LaunchServerRuntimeConfig();
runtimeConfig.reset();
} else {
LogHelper.info("Reading LaunchServer runtime config file");
try (BufferedReader reader = IOHelper.newReader(runtimeConfigFile)) {
runtimeConfig = Launcher.gsonManager.gson.fromJson(reader, LaunchServerRuntimeConfig.class);
}
}
generateConfigIfNotExists(configFile, localCommandHandler, env);
LogHelper.info("Reading LaunchServer config file");
try (BufferedReader reader = IOHelper.newReader(configFile)) {
config = Launcher.gsonManager.gson.fromJson(reader, LaunchServerConfig.class);
}
LaunchServer.LaunchServerConfigManager launchServerConfigManager = new LaunchServer.LaunchServerConfigManager() {
@Override
public LaunchServerConfig readConfig() throws IOException {
LaunchServerConfig config1;
try (BufferedReader reader = IOHelper.newReader(configFile)) {
config1 = Launcher.gsonManager.gson.fromJson(reader, LaunchServerConfig.class);
}
return config1;
}
@Override
public LaunchServerRuntimeConfig readRuntimeConfig() throws IOException {
LaunchServerRuntimeConfig config1;
try (BufferedReader reader = IOHelper.newReader(runtimeConfigFile)) {
config1 = Launcher.gsonManager.gson.fromJson(reader, LaunchServerRuntimeConfig.class);
}
return config1;
}
@Override
public void writeConfig(LaunchServerConfig config) throws IOException {
try (Writer writer = IOHelper.newWriter(configFile)) {
if (Launcher.gsonManager.configGson != null) {
Launcher.gsonManager.configGson.toJson(config, writer);
} else {
LogHelper.error("Error writing LaunchServer runtime config file. Gson is null");
}
}
}
@Override
public void writeRuntimeConfig(LaunchServerRuntimeConfig config) throws IOException {
try (Writer writer = IOHelper.newWriter(runtimeConfigFile)) {
if (Launcher.gsonManager.configGson != null) {
Launcher.gsonManager.configGson.toJson(config, writer);
} else {
LogHelper.error("Error writing LaunchServer runtime config file. Gson is null");
}
}
}
};
LaunchServer server = new LaunchServerBuilder()
.setDir(dir)
.setEnv(env)
.setCommandHandler(localCommandHandler)
.setPrivateKey(privateKey)
.setPublicKey(publicKey)
.setRuntimeConfig(runtimeConfig)
.setConfig(config)
.setModulesManager(modulesManager)
.setLaunchServerConfigManager(launchServerConfigManager)
.build();
server.run();
}
public static void initGson() {
Launcher.gsonManager = new LaunchServerGsonManager();
Launcher.gsonManager.initGson();
}
public static void registerAll()
{
AuthHandler.registerHandlers();
AuthProvider.registerProviders();
TextureProvider.registerProviders();
HWIDHandler.registerHandlers();
PermissionsHandler.registerHandlers();
Component.registerComponents();
ProtectHandler.registerHandlers();
WebSocketService.registerResponses();
HWIDProvider.registerHWIDs();
DaoProvider.registerProviders();
}
public static void generateConfigIfNotExists(Path configFile, CommandHandler commandHandler, LaunchServer.LaunchServerEnv env) throws IOException {
if (IOHelper.isFile(configFile))
return;
// Create new config
LogHelper.info("Creating LaunchServer config");
LaunchServerConfig newConfig = LaunchServerConfig.getDefault(env);
// Set server address
String address;
if (env.equals(LaunchServer.LaunchServerEnv.TEST)) {
address = "localhost";
newConfig.setProjectName("test");
} else {
System.out.println("LaunchServer address(default: localhost): ");
address = commandHandler.readLine();
System.out.println("LaunchServer projectName: ");
newConfig.setProjectName(commandHandler.readLine());
}
if (address == null || address.isEmpty()) {
LogHelper.error("Address null. Using localhost");
address = "localhost";
}
if (newConfig.projectName == null || newConfig.projectName.isEmpty()) {
LogHelper.error("ProjectName null. Using MineCraft");
newConfig.projectName = "MineCraft";
}
newConfig.netty.address = "ws://" + address + ":9274/api";
newConfig.netty.downloadURL = "http://" + address + ":9274/%dirname%/";
newConfig.netty.launcherURL = "http://" + address + ":9274/Launcher.jar";
newConfig.netty.launcherEXEURL = "http://" + address + ":9274/Launcher.exe";
// Write LaunchServer config
LogHelper.info("Writing LaunchServer config file");
try (BufferedWriter writer = IOHelper.newWriter(configFile)) {
Launcher.gsonManager.configGson.toJson(newConfig, writer);
}
}
}

View file

@ -25,6 +25,6 @@ public String getUsageDescription() {
public void invoke(String... args) throws Exception { public void invoke(String... args) throws Exception {
verifyArgs(args, 1); verifyArgs(args, 1);
URI uri = Paths.get(args[0]).toUri(); URI uri = Paths.get(args[0]).toUri();
server.modulesManager.loadModuleFull(uri.toURL()); server.modulesManager.loadModule(uri.toURL());
} }
} }

View file

@ -38,7 +38,7 @@ public void invoke(String... args) {
for (CommandHandler.Category category : server.commandHandler.getCategories()) { for (CommandHandler.Category category : server.commandHandler.getCategories()) {
commands += category.category.commandsMap().size(); commands += category.category.commandsMap().size();
} }
LogHelper.info("Sessions: %d | Modules: %d | Commands: %d(%d categories)", server.sessionManager.getSessions().size(), server.modulesManager.modules.size(), commands, server.commandHandler.getCategories().size() + 1); LogHelper.info("Sessions: %d | Commands: %d(%d categories)", server.sessionManager.getSessions().size(), commands, server.commandHandler.getCategories().size() + 1);
for (AuthProviderPair pair : server.config.auth) { for (AuthProviderPair pair : server.config.auth) {
if (pair.handler instanceof CachedAuthHandler) { if (pair.handler instanceof CachedAuthHandler) {
LogHelper.info("AuthHandler %s: EntryCache: %d | usernameCache: %d", pair.name, ((CachedAuthHandler) pair.handler).getEntryCache().size(), ((CachedAuthHandler) pair.handler).getUsernamesCache().size()); LogHelper.info("AuthHandler %s: EntryCache: %d | usernameCache: %d", pair.name, ((CachedAuthHandler) pair.handler).getEntryCache().size(), ((CachedAuthHandler) pair.handler).getUsernamesCache().size());

View file

@ -285,7 +285,7 @@ public static class GuardLicenseConf {
public String key; public String key;
public String encryptKey; public String encryptKey;
} }
public static LaunchServerConfig getDefault() public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env)
{ {
LaunchServerConfig newConfig = new LaunchServerConfig(); LaunchServerConfig newConfig = new LaunchServerConfig();
newConfig.mirrors = new String[]{"https://mirror.gravit.pro/"}; newConfig.mirrors = new String[]{"https://mirror.gravit.pro/"};

View file

@ -1,6 +1,7 @@
package pro.gravit.launchserver.manangers; package pro.gravit.launchserver.manangers;
import java.net.URL; import java.net.URL;
import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import pro.gravit.launcher.managers.SimpleModuleManager; import pro.gravit.launcher.managers.SimpleModuleManager;
@ -13,14 +14,18 @@
public class ModulesManager extends SimpleModuleManager { public class ModulesManager extends SimpleModuleManager {
public SimpleModulesConfigManager configManager; public SimpleModulesConfigManager configManager;
public ModulesManager(LaunchServer lsrv) { public ModulesManager(Path configDir) {
modules = new ArrayList<>(1); modules = new ArrayList<>(1);
configManager = new SimpleModulesConfigManager(lsrv.dir.resolve("config")); configManager = new SimpleModulesConfigManager(configDir);
classloader = new PublicURLClassLoader(new URL[0], ClassLoader.getSystemClassLoader()); classloader = new PublicURLClassLoader(new URL[0], ClassLoader.getSystemClassLoader());
context = new LaunchServerModuleContext(lsrv, classloader, configManager);
registerCoreModule(); registerCoreModule();
} }
public void initContext(LaunchServer server)
{
context = new LaunchServerModuleContext(server, classloader, configManager);
}
private void registerCoreModule() { private void registerCoreModule() {
load(new CoreModule()); load(new CoreModule());
} }

View file

@ -24,13 +24,13 @@ public static void prepare() {
@Test @Test
public void checkLaunchServerStarts() { public void checkLaunchServerStarts() {
try { /*try {
LaunchServer srv = new LaunchServer(dir, true, new String[]{"checkInstall"}); LaunchServer srv = new LaunchServer(dir, true, new String[]{"checkInstall"});
srv.run(); srv.run();
srv.commandHandler.eval(new String[]{"checkInstall"}, false); srv.commandHandler.eval(new String[]{"checkInstall"}, false);
srv.close(); srv.close();
} catch (InvalidKeySpecException | IOException e) { } catch (InvalidKeySpecException | IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }*/
} }
} }