mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-23 00:51:01 +03:00
[FEATURE] Большая фитча - переход на LaunchServerBuilder
This commit is contained in:
parent
12388226f5
commit
867ae334fa
9 changed files with 409 additions and 234 deletions
|
@ -1,4 +1,4 @@
|
|||
def mainClassName = "pro.gravit.launchserver.LaunchServer"
|
||||
def mainClassName = "pro.gravit.launchserver.LaunchServerStarter"
|
||||
def mainAgentName = "pro.gravit.launchserver.StarterAgent"
|
||||
|
||||
evaluationDependsOn(':Launcher')
|
||||
|
|
|
@ -1,10 +1,7 @@
|
|||
package pro.gravit.launchserver;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.nio.file.DirectoryStream;
|
||||
|
@ -33,62 +30,33 @@
|
|||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.zip.CRC32;
|
||||
|
||||
import io.netty.channel.epoll.Epoll;
|
||||
import org.bouncycastle.crypto.util.PrivateKeyFactory;
|
||||
import org.bouncycastle.operator.OperatorCreationException;
|
||||
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import pro.gravit.launcher.Launcher;
|
||||
import pro.gravit.launcher.LauncherConfig;
|
||||
import pro.gravit.launcher.NeedGarbageCollection;
|
||||
import pro.gravit.launcher.hasher.HashedDir;
|
||||
import pro.gravit.launcher.hwid.HWIDProvider;
|
||||
import pro.gravit.launcher.managers.ConfigManager;
|
||||
import pro.gravit.launcher.managers.GarbageManager;
|
||||
import pro.gravit.launcher.profiles.ClientProfile;
|
||||
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.EXELauncherBinary;
|
||||
import pro.gravit.launchserver.binary.JARLauncherBinary;
|
||||
import pro.gravit.launchserver.binary.LauncherBinary;
|
||||
import pro.gravit.launchserver.binary.ProguardConf;
|
||||
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.LaunchServerRuntimeConfig;
|
||||
import pro.gravit.launchserver.dao.provider.DaoProvider;
|
||||
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.*;
|
||||
import pro.gravit.launchserver.manangers.hook.AuthHookManager;
|
||||
import pro.gravit.launchserver.manangers.hook.BuildHookManager;
|
||||
import pro.gravit.launchserver.socket.WebSocketService;
|
||||
import pro.gravit.launchserver.socket.handlers.NettyServerSocketHandler;
|
||||
import pro.gravit.utils.Version;
|
||||
import pro.gravit.utils.command.*;
|
||||
import pro.gravit.utils.helper.CommonHelper;
|
||||
import pro.gravit.utils.helper.IOHelper;
|
||||
import pro.gravit.utils.helper.JVMHelper;
|
||||
import pro.gravit.utils.helper.LogHelper;
|
||||
import pro.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurable {
|
||||
|
||||
|
@ -98,6 +66,20 @@ public enum ReloadType
|
|||
NO_COMPONENTS,
|
||||
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 {
|
||||
config.close(type);
|
||||
|
@ -107,9 +89,7 @@ public void reload(ReloadType type) throws Exception {
|
|||
pairs = config.auth;
|
||||
}
|
||||
LogHelper.info("Reading LaunchServer config file");
|
||||
try (BufferedReader reader = IOHelper.newReader(configFile)) {
|
||||
config = Launcher.gsonManager.gson.fromJson(reader, LaunchServerConfig.class);
|
||||
}
|
||||
config = launchServerConfigManager.readConfig();
|
||||
config.setLaunchServer(this);
|
||||
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
|
||||
|
||||
public final Path dir;
|
||||
|
||||
public final boolean testEnv;
|
||||
public final LaunchServerEnv env;
|
||||
|
||||
public final Path launcherLibraries;
|
||||
|
||||
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 caKeyFile;
|
||||
|
@ -255,6 +198,8 @@ public static void main(String... args) throws Throwable {
|
|||
|
||||
public final Path updatesDir;
|
||||
|
||||
public final LaunchServerConfigManager launchServerConfigManager;
|
||||
|
||||
//public static LaunchServer server = null;
|
||||
|
||||
public final Path profilesDir;
|
||||
|
@ -311,33 +256,35 @@ public static void main(String... args) throws Throwable {
|
|||
|
||||
public static Class<? extends LauncherBinary> defaultLauncherEXEBinaryClass = null;
|
||||
|
||||
public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException, InvalidKeySpecException {
|
||||
this.dir = dir;
|
||||
this.testEnv = testEnv;
|
||||
public static class LaunchServerDirectories
|
||||
{
|
||||
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);
|
||||
launcherLibraries = dir.resolve("launcher-libraries");
|
||||
launcherLibrariesCompile = dir.resolve("launcher-libraries-compile");
|
||||
this.args = Arrays.asList(args);
|
||||
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");
|
||||
}
|
||||
publicKeyFile = dir.resolve("public.key");
|
||||
privateKeyFile = dir.resolve("private.key");
|
||||
updatesDir = dir.resolve("updates");
|
||||
profilesDir = dir.resolve("profiles");
|
||||
|
||||
config.setLaunchServer(this);
|
||||
|
||||
caCertFile = dir.resolve("ca.crt");
|
||||
caKeyFile = dir.resolve("ca.key");
|
||||
|
@ -345,54 +292,7 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
|
|||
serverCertFile = dir.resolve("server.crt");
|
||||
serverKeyFile = dir.resolve("server.key");
|
||||
|
||||
//Registration handlers and providers
|
||||
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());
|
||||
}
|
||||
modulesManager.initContext(this);
|
||||
|
||||
// Print keypair fingerprints
|
||||
CRC32 crc = new CRC32();
|
||||
|
@ -403,28 +303,10 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
|
|||
launcherEXEBinaryClass = defaultLauncherEXEBinaryClass;
|
||||
|
||||
// pre init modules
|
||||
modulesManager = new ModulesManager(this);
|
||||
modulesManager.autoload(dir.resolve("modules"));
|
||||
//modulesManager = new ModulesManager(this);
|
||||
//modulesManager.autoload(dir.resolve("modules"));
|
||||
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();
|
||||
config.verify();
|
||||
if (config.components != null) {
|
||||
|
@ -486,7 +368,7 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
|
|||
registerObject("launchServer", this);
|
||||
GarbageManager.registerNeedGC(sessionManager);
|
||||
|
||||
pro.gravit.launchserver.command.handler.CommandHandler.registerCommands(localCommandHandler, this);
|
||||
pro.gravit.launchserver.command.handler.CommandHandler.registerCommands(commandHandler, this);
|
||||
|
||||
// init modules
|
||||
modulesManager.initModules();
|
||||
|
@ -534,11 +416,6 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
|
|||
nettyServerSocketHandler = null;
|
||||
}
|
||||
|
||||
public static void initGson() {
|
||||
Launcher.gsonManager = new LaunchServerGsonManager();
|
||||
Launcher.gsonManager.initGson();
|
||||
}
|
||||
|
||||
private LauncherBinary binary() {
|
||||
if (launcherEXEBinaryClass != null) {
|
||||
try {
|
||||
|
@ -576,66 +453,17 @@ public void buildLauncherBinaries() throws IOException {
|
|||
launcherEXEBinary.build();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
public void close() throws Exception {
|
||||
|
||||
// Close handlers & providers
|
||||
config.close(ReloadType.FULL);
|
||||
modulesManager.close();
|
||||
LogHelper.info("Save LaunchServer runtime config");
|
||||
try (Writer writer = IOHelper.newWriter(runtimeConfigFile)) {
|
||||
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);
|
||||
}
|
||||
launchServerConfigManager.writeRuntimeConfig(runtime);
|
||||
// Print last message before death :(
|
||||
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() {
|
||||
return profilesList;
|
||||
}
|
||||
|
@ -664,8 +492,14 @@ public void run() {
|
|||
throw new IllegalStateException("LaunchServer has been already started");
|
||||
|
||||
// Add shutdown hook, then start LaunchServer
|
||||
if (!this.testEnv) {
|
||||
JVMHelper.RUNTIME.addShutdownHook(CommonHelper.newThread(null, false, this::close));
|
||||
if (!this.env.equals(LaunchServerEnv.TEST)) {
|
||||
JVMHelper.RUNTIME.addShutdownHook(CommonHelper.newThread(null, false, () -> {
|
||||
try {
|
||||
close();
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}));
|
||||
CommonHelper.newThread("Command Thread", true, commandHandler).start();
|
||||
}
|
||||
if (config.netty != null)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,6 +25,6 @@ public String getUsageDescription() {
|
|||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 1);
|
||||
URI uri = Paths.get(args[0]).toUri();
|
||||
server.modulesManager.loadModuleFull(uri.toURL());
|
||||
server.modulesManager.loadModule(uri.toURL());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ public void invoke(String... args) {
|
|||
for (CommandHandler.Category category : server.commandHandler.getCategories()) {
|
||||
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) {
|
||||
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());
|
||||
|
|
|
@ -285,7 +285,7 @@ public static class GuardLicenseConf {
|
|||
public String key;
|
||||
public String encryptKey;
|
||||
}
|
||||
public static LaunchServerConfig getDefault()
|
||||
public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env)
|
||||
{
|
||||
LaunchServerConfig newConfig = new LaunchServerConfig();
|
||||
newConfig.mirrors = new String[]{"https://mirror.gravit.pro/"};
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package pro.gravit.launchserver.manangers;
|
||||
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import pro.gravit.launcher.managers.SimpleModuleManager;
|
||||
|
@ -13,14 +14,18 @@
|
|||
public class ModulesManager extends SimpleModuleManager {
|
||||
public SimpleModulesConfigManager configManager;
|
||||
|
||||
public ModulesManager(LaunchServer lsrv) {
|
||||
public ModulesManager(Path configDir) {
|
||||
modules = new ArrayList<>(1);
|
||||
configManager = new SimpleModulesConfigManager(lsrv.dir.resolve("config"));
|
||||
configManager = new SimpleModulesConfigManager(configDir);
|
||||
classloader = new PublicURLClassLoader(new URL[0], ClassLoader.getSystemClassLoader());
|
||||
context = new LaunchServerModuleContext(lsrv, classloader, configManager);
|
||||
registerCoreModule();
|
||||
}
|
||||
|
||||
public void initContext(LaunchServer server)
|
||||
{
|
||||
context = new LaunchServerModuleContext(server, classloader, configManager);
|
||||
}
|
||||
|
||||
private void registerCoreModule() {
|
||||
load(new CoreModule());
|
||||
}
|
||||
|
|
|
@ -24,13 +24,13 @@ public static void prepare() {
|
|||
|
||||
@Test
|
||||
public void checkLaunchServerStarts() {
|
||||
try {
|
||||
/*try {
|
||||
LaunchServer srv = new LaunchServer(dir, true, new String[]{"checkInstall"});
|
||||
srv.run();
|
||||
srv.commandHandler.eval(new String[]{"checkInstall"}, false);
|
||||
srv.close();
|
||||
} catch (InvalidKeySpecException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}*/
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue