mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-22 16:41:46 +03:00
Merge branch 'release/5.0.0b3'
This commit is contained in:
commit
5e0bcf5154
36 changed files with 367 additions and 348 deletions
|
@ -1,5 +1,6 @@
|
|||
package ru.gravit.launchserver;
|
||||
|
||||
import io.netty.handler.logging.LogLevel;
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.launcher.LauncherConfig;
|
||||
import ru.gravit.launcher.NeedGarbageCollection;
|
||||
|
@ -79,6 +80,8 @@ public static final class Config {
|
|||
public String[] mirrors;
|
||||
|
||||
public String binaryName;
|
||||
|
||||
public boolean copyBinaries = true;
|
||||
|
||||
public LauncherConfig.LauncherEnvironment env;
|
||||
|
||||
|
@ -269,7 +272,7 @@ public class LauncherConf
|
|||
}
|
||||
|
||||
public class NettyConfig {
|
||||
public boolean clientEnabled;
|
||||
public boolean fileServerEnabled;
|
||||
public boolean sendExceptionEnabled;
|
||||
public String launcherURL;
|
||||
public String downloadURL;
|
||||
|
@ -278,6 +281,7 @@ public class NettyConfig {
|
|||
public Map<String, String> bindings = new HashMap<>();
|
||||
public NettyPerformanceConfig performance;
|
||||
public NettyBindAddress[] binds;
|
||||
public LogLevel logLevel = LogLevel.DEBUG;
|
||||
}
|
||||
public class NettyPerformanceConfig
|
||||
{
|
||||
|
@ -678,6 +682,7 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
|||
Config newConfig = new Config();
|
||||
newConfig.mirrors = new String[]{"http://mirror.gravitlauncher.ml/", "https://mirror.gravit.pro/"};
|
||||
newConfig.launch4j = new ExeConf();
|
||||
newConfig.launch4j.enabled = true;
|
||||
newConfig.launch4j.copyright = "© GravitLauncher Team";
|
||||
newConfig.launch4j.fileDesc = "GravitLauncher ".concat(Launcher.getVersion().getVersionString());
|
||||
newConfig.launch4j.fileVer = Launcher.getVersion().getVersionString().concat(".").concat(String.valueOf(Launcher.getVersion().patch));
|
||||
|
@ -704,11 +709,7 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
|||
newConfig.whitelistRejectString = "Вас нет в белом списке";
|
||||
|
||||
newConfig.netty = new NettyConfig();
|
||||
newConfig.netty.address = "ws://localhost:9274/api";
|
||||
newConfig.netty.downloadURL = "http://localhost:9274/%dirname%/";
|
||||
newConfig.netty.launcherURL = "http://localhost:9274/Launcher.jar";
|
||||
newConfig.netty.launcherEXEURL = "http://localhost:9274/Launcher.exe";
|
||||
newConfig.netty.clientEnabled = false;
|
||||
newConfig.netty.fileServerEnabled = true;
|
||||
newConfig.netty.binds = new NettyBindAddress[]{ new NettyBindAddress("0.0.0.0", 9274) };
|
||||
newConfig.netty.performance = new NettyPerformanceConfig();
|
||||
newConfig.netty.performance.bossThread = 2;
|
||||
|
@ -720,7 +721,7 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
|||
newConfig.threadCoreCount = 0; // on your own
|
||||
newConfig.threadCount = JVMHelper.OPERATING_SYSTEM_MXBEAN.getAvailableProcessors() >= 4 ? JVMHelper.OPERATING_SYSTEM_MXBEAN.getAvailableProcessors() / 2 : JVMHelper.OPERATING_SYSTEM_MXBEAN.getAvailableProcessors();
|
||||
|
||||
newConfig.enabledRadon = true;
|
||||
newConfig.enabledRadon = false;
|
||||
newConfig.enabledProGuard = true;
|
||||
newConfig.stripLineNumbers = true;
|
||||
newConfig.deleteTempFiles = true;
|
||||
|
@ -734,25 +735,33 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
|||
newConfig.components.put("authLimiter", authLimiterComponent);
|
||||
|
||||
// Set server address
|
||||
String address;
|
||||
if (testEnv) {
|
||||
newConfig.setLegacyAddress("localhost");
|
||||
address = "localhost";
|
||||
newConfig.setProjectName("test");
|
||||
} else {
|
||||
System.out.println("LaunchServer legacy address(default: localhost): ");
|
||||
newConfig.setLegacyAddress(commandHandler.readLine());
|
||||
System.out.println("LaunchServer address(default: localhost): ");
|
||||
address = commandHandler.readLine();
|
||||
System.out.println("LaunchServer projectName: ");
|
||||
newConfig.setProjectName(commandHandler.readLine());
|
||||
}
|
||||
if(newConfig.legacyAddress == null)
|
||||
if(address == null)
|
||||
{
|
||||
LogHelper.error("Legacy address null. Using localhost");
|
||||
newConfig.legacyAddress = "localhost";
|
||||
LogHelper.error("Address null. Using localhost");
|
||||
address = "localhost";
|
||||
}
|
||||
if(newConfig.projectName == null)
|
||||
{
|
||||
LogHelper.error("ProjectName null. Using MineCraft");
|
||||
newConfig.projectName = "MineCraft";
|
||||
}
|
||||
|
||||
newConfig.legacyAddress = address;
|
||||
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";
|
||||
newConfig.netty.sendExceptionEnabled = true;
|
||||
|
||||
// Write LaunchServer config
|
||||
LogHelper.info("Writing LaunchServer config file");
|
||||
|
@ -836,14 +845,14 @@ public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
|||
LogHelper.info("Syncing updates dir");
|
||||
Map<String, SignedObjectHolder<HashedDir>> newUpdatesDirMap = new HashMap<>(16);
|
||||
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(updatesDir)) {
|
||||
for (Path updateDir : dirStream) {
|
||||
for (final Path updateDir : dirStream) {
|
||||
if (Files.isHidden(updateDir))
|
||||
continue; // Skip hidden
|
||||
|
||||
// Resolve name and verify is dir
|
||||
String name = IOHelper.getFileName(updateDir);
|
||||
if (!IOHelper.isDir(updateDir)) {
|
||||
LogHelper.warning("Not update dir: '%s'", name);
|
||||
if (!IOHelper.isFile(updateDir) && Arrays.asList(".jar", ".exe", ".hash").stream().noneMatch(e -> updateDir.toString().endsWith(e))) LogHelper.warning("Not update dir: '%s'", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ public void clear() {
|
|||
|
||||
|
||||
public EXEL4JLauncherBinary(LaunchServer server) {
|
||||
super(server, server.dir.resolve(server.config.binaryName + ".exe"));
|
||||
super(server, LauncherBinary.resolve(server, ".exe"));
|
||||
faviconFile = server.dir.resolve("favicon.ico");
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
public class EXELauncherBinary extends LauncherBinary {
|
||||
|
||||
public EXELauncherBinary(LaunchServer server) {
|
||||
super(server, server.dir.resolve(server.config.binaryName + ".exe"));
|
||||
super(server, LauncherBinary.resolve(server, ".exe"));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,9 +24,8 @@ public final class JARLauncherBinary extends LauncherBinary {
|
|||
public List<Path> addonLibs;
|
||||
|
||||
public JARLauncherBinary(LaunchServer server) throws IOException {
|
||||
super(server);
|
||||
super(server, LauncherBinary.resolve(server, ".jar"));
|
||||
count = new AtomicLong(0);
|
||||
syncBinaryFile = server.dir.resolve(server.config.binaryName + ".jar");
|
||||
runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR);
|
||||
guardDir = server.dir.resolve(Launcher.GUARD_DIR);
|
||||
buildDir = server.dir.resolve("build");
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
public abstract class LauncherBinary {
|
||||
public final LaunchServer server;
|
||||
public Path syncBinaryFile;
|
||||
public final Path syncBinaryFile;
|
||||
private volatile DigestBytesHolder binary;
|
||||
private volatile byte[] sign;
|
||||
|
||||
|
@ -19,10 +19,6 @@ protected LauncherBinary(LaunchServer server, Path binaryFile) {
|
|||
syncBinaryFile = binaryFile;
|
||||
}
|
||||
|
||||
protected LauncherBinary(LaunchServer server) {
|
||||
this.server = server;
|
||||
}
|
||||
|
||||
public abstract void build() throws IOException;
|
||||
|
||||
|
||||
|
@ -49,4 +45,8 @@ public final boolean sync() throws IOException {
|
|||
|
||||
return exists;
|
||||
}
|
||||
|
||||
public static final Path resolve(LaunchServer server, String ext) {
|
||||
return server.config.copyBinaries ? server.updatesDir.resolve(server.config.binaryName + ext) : server.dir.resolve(server.config.binaryName + ext);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ public LauncherNettyServer() {
|
|||
serverBootstrap = new ServerBootstrap();
|
||||
serverBootstrap.group(bossGroup, workerGroup)
|
||||
.channel(NioServerSocketChannel.class)
|
||||
.handler(new LoggingHandler(LogLevel.DEBUG))
|
||||
.handler(new LoggingHandler(config.logLevel))
|
||||
.childHandler(new ChannelInitializer<NioSocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(NioSocketChannel ch) {
|
||||
|
@ -42,7 +42,7 @@ public void initChannel(NioSocketChannel ch) {
|
|||
pipeline.addLast(new HttpObjectAggregator(65536));
|
||||
pipeline.addLast(new WebSocketServerCompressionHandler());
|
||||
pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
|
||||
pipeline.addLast(new FileServerHandler(LaunchServer.server.updatesDir, true));
|
||||
if (LaunchServer.server.config.netty.fileServerEnabled) pipeline.addLast(new FileServerHandler(LaunchServer.server.updatesDir, true));
|
||||
pipeline.addLast(new WebSocketFrameHandler());
|
||||
}
|
||||
});
|
||||
|
|
|
@ -60,7 +60,7 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
|||
try {
|
||||
AuthRequestEvent result = new AuthRequestEvent();
|
||||
String ip = IOHelper.getIP(ctx.channel().remoteAddress());
|
||||
if ((authType == null || authType == ConnectTypes.CLIENT) && !clientData.checkSign) {
|
||||
if ((authType == null || authType == ConnectTypes.CLIENT) && ( clientData == null || !clientData.checkSign )) {
|
||||
AuthProvider.authError("Don't skip Launcher Update");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -20,9 +20,9 @@
|
|||
-keepattributes Signature
|
||||
-adaptresourcefilecontents META-INF/MANIFEST.MF
|
||||
|
||||
-keeppackagenames com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,oshi.**,com.sun.jna.**,com.google.gson.**,org.slf4j.**,oshi.jna.**,com.sun.jna.**,org.apache.commons.logging.**, org.fusesource.**, com.jfoenix.**
|
||||
-keeppackagenames com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,com.google.gson.**,ru.gravit.repackage.**,org.fusesource.**
|
||||
|
||||
-keep class com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,oshi.**,com.sun.jna.**,com.google.gson.**,org.slf4j.**,oshi.jna.**,com.sun.jna.**,org.apache.commons.logging.**, org.fusesource.**, com.jfoenix.** {
|
||||
-keep class com.mojang.**,net.minecraftforge.fml.**,cpw.mods.fml.**,com.google.gson.**,ru.gravit.repackage.**,org.fusesource.** {
|
||||
*;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,16 +30,18 @@
|
|||
shadowJar {
|
||||
classifier = null
|
||||
relocate 'org.objectweb.asm', 'ru.gravit.repackage.org.objectweb.asm'
|
||||
relocate 'io.netty', 'ru.gravit.repackage.io.netty'
|
||||
configurations = [project.configurations.pack]
|
||||
exclude 'module-info.class'
|
||||
}
|
||||
|
||||
dependencies {
|
||||
pack project(':LauncherAPI') // Not error on obf.
|
||||
pack project(':LauncherAPI')
|
||||
bundle 'com.github.oshi:oshi-core:3.13.0'
|
||||
bundle 'com.jfoenix:jfoenix:8.0.8'
|
||||
bundle 'de.jensd:fontawesomefx:8.9'
|
||||
bundle 'org.fusesource.jansi:jansi:1.17.1'
|
||||
bundle 'org.apache.httpcomponents:httpclient:4.5.7'
|
||||
pack 'io.netty:netty-all:4.1.32.Final'
|
||||
pack 'org.ow2.asm:asm-tree:7.1'
|
||||
}
|
||||
|
||||
|
|
|
@ -59,6 +59,8 @@ function initLoginScene() {
|
|||
savePasswordBox = pane.lookup("#rememberchb");
|
||||
savePasswordBox.setSelected(settings.login === null || settings.rsaPassword !== null);
|
||||
|
||||
authOptions = pane.lookup("#authOptions");
|
||||
|
||||
var link = pane.lookup("#link");
|
||||
link.setText(config.linkText);
|
||||
link.setOnAction(function(event) app.getHostServices().showDocument(config.linkURL.toURI()));
|
||||
|
@ -466,4 +468,4 @@ launcher.loadScript("dialog/overlay/update/update.js");
|
|||
|
||||
/* ======== Scenes scripts ======== */
|
||||
launcher.loadScript("dialog/scenes/options/options.js");
|
||||
launcher.loadScript("dialog/scenes/console/console.js");
|
||||
launcher.loadScript("dialog/scenes/console/console.js");
|
||||
|
|
|
@ -42,7 +42,7 @@ var settingsOverlay = {
|
|||
settingsOverlay.updateRAMLabel();
|
||||
|
||||
var ramSlider = holder.lookup("#ramSlider");
|
||||
ramSlider.setMax(JVMHelper.RAM);
|
||||
ramSlider.setMax(FunctionalBridge.getJVMTotalMemory());
|
||||
ramSlider.setSnapToTicks(true);
|
||||
ramSlider.setShowTickMarks(true);
|
||||
ramSlider.setShowTickLabels(true);
|
||||
|
|
|
@ -7,7 +7,8 @@
|
|||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.InsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
import ru.gravit.utils.NativeJVMHalt;
|
||||
|
||||
import ru.gravit.launcher.utils.NativeJVMHalt;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
import ru.gravit.launcher.managers.ClientGsonManager;
|
||||
import ru.gravit.launcher.managers.ConsoleManager;
|
||||
import ru.gravit.launcher.request.Request;
|
||||
import ru.gravit.launcher.request.websockets.ClientWebSocketService;
|
||||
import ru.gravit.launcher.request.RequestException;
|
||||
import ru.gravit.launcher.request.auth.RestoreSessionRequest;
|
||||
import ru.gravit.launcher.request.websockets.StandartClientWebSocketService;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.EnvHelper;
|
||||
|
@ -72,11 +73,28 @@ public void start(String... args) throws Throwable {
|
|||
if (runtimeProvider == null) runtimeProvider = new JSRuntimeProvider();
|
||||
runtimeProvider.init(false);
|
||||
runtimeProvider.preLoad();
|
||||
if(Request.service != null)
|
||||
if(Request.service == null)
|
||||
{
|
||||
String address = Launcher.getConfig().address;
|
||||
LogHelper.debug("Start async connection to %s", address);
|
||||
Request.service = StandartClientWebSocketService.initWebSockets(address, true);
|
||||
Request.service.reconnectCallback = () ->
|
||||
{
|
||||
LogHelper.debug("WebSocket connect closed. Try reconnect");
|
||||
try {
|
||||
Request.service.open();
|
||||
LogHelper.debug("Connect to %s", Launcher.getConfig().address);
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
throw new RequestException(String.format("Connect error: %s", e.getMessage() != null ? e.getMessage() : "null"));
|
||||
}
|
||||
try {
|
||||
RestoreSessionRequest request1 = new RestoreSessionRequest(Request.getSession());
|
||||
request1.request();
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
LauncherGuardManager.initGuard(false);
|
||||
Objects.requireNonNull(args, "args");
|
||||
|
|
|
@ -3,17 +3,18 @@
|
|||
import ru.gravit.launcher.*;
|
||||
import ru.gravit.launcher.guard.LauncherGuardManager;
|
||||
import ru.gravit.launcher.gui.JSRuntimeProvider;
|
||||
import ru.gravit.launcher.hasher.DirWatcher;
|
||||
import ru.gravit.launcher.hasher.FileNameMatcher;
|
||||
import ru.gravit.launcher.hasher.HashedDir;
|
||||
import ru.gravit.launcher.managers.ClientGsonManager;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.profiles.PlayerProfile;
|
||||
import ru.gravit.launcher.request.Request;
|
||||
import ru.gravit.launcher.request.RequestException;
|
||||
import ru.gravit.launcher.request.auth.RestoreSessionRequest;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.stream.StreamObject;
|
||||
import ru.gravit.launcher.utils.DirWatcher;
|
||||
import ru.gravit.utils.PublicURLClassLoader;
|
||||
import ru.gravit.utils.helper.*;
|
||||
import ru.gravit.utils.helper.JVMHelper.OS;
|
||||
|
@ -36,7 +37,6 @@
|
|||
import java.util.*;
|
||||
|
||||
public final class ClientLauncher {
|
||||
|
||||
private static final class ClassPathFileVisitor extends SimpleFileVisitor<Path> {
|
||||
private final Collection<Path> result;
|
||||
|
||||
|
@ -328,7 +328,7 @@ public static Process launch(
|
|||
context.playerProfile = params.pp;
|
||||
context.args.add(javaBin.toString());
|
||||
context.args.add(MAGICAL_INTEL_OPTION);
|
||||
if (params.ram > 0 && params.ram <= JVMHelper.RAM) {
|
||||
if (params.ram > 0 && params.ram <= FunctionalBridge.getJVMTotalMemory()) {
|
||||
context.args.add("-Xms" + params.ram + 'M');
|
||||
context.args.add("-Xmx" + params.ram + 'M');
|
||||
}
|
||||
|
@ -460,10 +460,11 @@ public static void main(String... args) throws Throwable {
|
|||
{
|
||||
LogHelper.debug("WebSocket connect closed. Try reconnect");
|
||||
try {
|
||||
if (!Request.service.reconnectBlocking()) LogHelper.error("Error connecting");
|
||||
Request.service.open();
|
||||
LogHelper.debug("Connect to %s", Launcher.getConfig().address);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
throw new RequestException(String.format("Connect error: %s", e.getMessage() != null ? e.getMessage() : "null"));
|
||||
}
|
||||
try {
|
||||
RestoreSessionRequest request1 = new RestoreSessionRequest(Request.getSession());
|
||||
|
@ -537,8 +538,21 @@ public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher,
|
|||
|
||||
// Hash directory and compare (ignore update-only matcher entries, it will break offline-mode)
|
||||
HashedDir currentHDir = new HashedDir(dir, matcher, true, digest);
|
||||
if (!hdir.diff(currentHDir, matcher).isSame())
|
||||
HashedDir.Diff diff = hdir.diff(currentHDir, matcher);
|
||||
if (!diff.isSame())
|
||||
{
|
||||
/*AtomicBoolean isFoundFile = new AtomicBoolean(false);
|
||||
diff.extra.walk(File.separator, (e,k,v) -> {
|
||||
if(v.getType().equals(HashedEntry.Type.FILE)) { LogHelper.error("Extra file %s", e); isFoundFile.set(true); }
|
||||
else LogHelper.error("Extra %s", e);
|
||||
});
|
||||
diff.mismatch.walk(File.separator, (e,k,v) -> {
|
||||
if(v.getType().equals(HashedEntry.Type.FILE)) { LogHelper.error("Mismatch file %s", e); isFoundFile.set(true); }
|
||||
else LogHelper.error("Mismatch %s", e);
|
||||
});
|
||||
if(isFoundFile.get())*/
|
||||
throw new SecurityException(String.format("Forbidden modification: '%s'", IOHelper.getFileName(dir)));
|
||||
}
|
||||
}
|
||||
|
||||
private ClientLauncher() {
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
import ru.gravit.launcher.managers.HasherManager;
|
||||
import ru.gravit.launcher.managers.HasherStore;
|
||||
import ru.gravit.launcher.request.Request;
|
||||
import ru.gravit.launcher.request.websockets.RequestInterface;
|
||||
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
|
@ -30,6 +29,8 @@ public class FunctionalBridge {
|
|||
public static AtomicReference<HWID> hwid = new AtomicReference<>();
|
||||
@LauncherAPI
|
||||
public static Thread getHWID = null;
|
||||
|
||||
private static long cachedMemorySize = -1;
|
||||
|
||||
@LauncherAPI
|
||||
public static HashedDirRunnable offlineUpdateRequest(String dirName, Path dir, SignedObjectHolder<HashedDir> hdir, FileNameMatcher matcher, boolean digest) {
|
||||
|
@ -42,11 +43,6 @@ public static HashedDirRunnable offlineUpdateRequest(String dirName, Path dir, S
|
|||
};
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void makeJsonRequest(RequestInterface request, Runnable callback) {
|
||||
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void startTask(Runnable task) {
|
||||
threadPool.execute(task);
|
||||
|
@ -60,8 +56,9 @@ public static HWID getHWID() {
|
|||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static long getTotalMemory() {
|
||||
return hwidProvider.getTotalMemory() >> 20;
|
||||
public static int getTotalMemory() {
|
||||
if (cachedMemorySize > 0) return (int)cachedMemorySize;
|
||||
return (int)(cachedMemorySize = hwidProvider.getTotalMemory() >> 20);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
|
@ -70,7 +67,7 @@ public static int getClientJVMBits() {
|
|||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static long getJVMTotalMemory() {
|
||||
public static int getJVMTotalMemory() {
|
||||
if (getClientJVMBits() == 32) {
|
||||
return Math.min(getTotalMemory(), 1536);
|
||||
} else {
|
||||
|
@ -106,6 +103,7 @@ public static void setAuthParams(AuthRequestEvent event) {
|
|||
public interface HashedDirRunnable {
|
||||
SignedObjectHolder<HashedDir> run() throws Exception;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void evalCommand(String cmd)
|
||||
{
|
||||
|
|
|
@ -83,7 +83,7 @@ public String getMacAddr() {
|
|||
}
|
||||
|
||||
public long getTotalMemory() {
|
||||
if (noHWID) return -1;
|
||||
if (noHWID) return 1024<<20;
|
||||
if (hardware == null) hardware = systemInfo.getHardware();
|
||||
return hardware.getMemory().getTotal();
|
||||
}
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
package ru.gravit.launcher.hasher;
|
||||
package ru.gravit.launcher.utils;
|
||||
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.hasher.FileNameMatcher;
|
||||
import ru.gravit.launcher.hasher.HashedDir;
|
||||
import ru.gravit.launcher.hasher.HashedEntry;
|
||||
import ru.gravit.launcher.hasher.HashedFile;
|
||||
import ru.gravit.launcher.hasher.HashedEntry.Type;
|
||||
import ru.gravit.utils.NativeJVMHalt;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.JVMHelper;
|
||||
import ru.gravit.utils.helper.JVMHelper.OS;
|
|
@ -1,4 +1,4 @@
|
|||
package ru.gravit.utils;
|
||||
package ru.gravit.launcher.utils;
|
||||
|
||||
import cpw.mods.fml.SafeExitJVMLegacy;
|
||||
import net.minecraftforge.fml.SafeExitJVM;
|
|
@ -3,8 +3,8 @@
|
|||
|
||||
dependencies {
|
||||
compile project(':libLauncher')
|
||||
compile 'org.java-websocket:Java-WebSocket:1.3.9'
|
||||
compile 'org.apache.httpcomponents:httpclient:4.5.7'
|
||||
compileOnly 'io.netty:netty-all:4.1.32.Final'
|
||||
compileOnly 'org.apache.httpcomponents:httpclient:4.5.7'
|
||||
compileOnly 'com.google.guava:guava:26.0-jre'
|
||||
compile files('../compat/authlib/authlib-clean.jar')
|
||||
}
|
||||
|
|
|
@ -174,11 +174,19 @@ public UpdateRequestEvent requestDo() throws Exception {
|
|||
HashedDir.Diff diff = e.hdir.diff(localDir, matcher);
|
||||
final List<ListDownloader.DownloadTask> adds = new ArrayList<>();
|
||||
diff.mismatch.walk(IOHelper.CROSS_SEPARATOR, (path, name, entry) -> {
|
||||
if(entry.getType() == HashedEntry.Type.FILE) {
|
||||
if(entry.getType().equals(HashedEntry.Type.FILE)) {
|
||||
HashedFile file = (HashedFile) entry;
|
||||
totalSize += file.size;
|
||||
adds.add(new ListDownloader.DownloadTask(path, file.size));
|
||||
}
|
||||
else if(entry.getType().equals(HashedEntry.Type.DIR))
|
||||
{
|
||||
try {
|
||||
Files.createDirectories(dir.resolve(path));
|
||||
} catch (IOException ex) {
|
||||
LogHelper.error(ex);
|
||||
}
|
||||
}
|
||||
});
|
||||
totalSize = diff.mismatch.size();
|
||||
startTime = Instant.now();
|
||||
|
|
|
@ -1,36 +1,101 @@
|
|||
package ru.gravit.launcher.request.websockets;
|
||||
|
||||
import org.java_websocket.client.WebSocketClient;
|
||||
import org.java_websocket.drafts.Draft_6455;
|
||||
import org.java_websocket.handshake.ServerHandshake;
|
||||
import io.netty.bootstrap.Bootstrap;
|
||||
import io.netty.channel.*;
|
||||
import io.netty.channel.nio.NioEventLoopGroup;
|
||||
import io.netty.channel.socket.SocketChannel;
|
||||
import io.netty.channel.socket.nio.NioSocketChannel;
|
||||
import io.netty.handler.codec.http.EmptyHttpHeaders;
|
||||
import io.netty.handler.codec.http.HttpClientCodec;
|
||||
import io.netty.handler.codec.http.HttpObjectAggregator;
|
||||
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
|
||||
import io.netty.handler.ssl.SslContext;
|
||||
import io.netty.handler.ssl.SslContextBuilder;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
public class ClientJSONPoint extends WebSocketClient {
|
||||
public abstract class ClientJSONPoint {
|
||||
|
||||
public ClientJSONPoint(URI serverUri, Map<String, String> httpHeaders, int connectTimeout) {
|
||||
super(serverUri, new Draft_6455(), httpHeaders, connectTimeout);
|
||||
private final URI uri;
|
||||
protected Channel ch;
|
||||
private static final EventLoopGroup group = new NioEventLoopGroup();
|
||||
protected WebSocketClientHandler webSocketClientHandler;
|
||||
protected Bootstrap bootstrap = new Bootstrap();
|
||||
public boolean isClosed;
|
||||
|
||||
public ClientJSONPoint(final String uri) throws SSLException {
|
||||
this(URI.create(uri));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(ServerHandshake handshakedata) {
|
||||
|
||||
public ClientJSONPoint(URI uri) throws SSLException {
|
||||
this.uri = uri;
|
||||
String protocol = uri.getScheme();
|
||||
if (!"ws".equals(protocol) && !"wss".equals(protocol)) {
|
||||
throw new IllegalArgumentException("Unsupported protocol: " + protocol);
|
||||
}
|
||||
boolean ssl = false;
|
||||
if("wss".equals(protocol))
|
||||
{
|
||||
ssl = true;
|
||||
}
|
||||
final SslContext sslCtx;
|
||||
if (ssl) {
|
||||
sslCtx = SslContextBuilder.forClient().build();
|
||||
} else sslCtx = null;
|
||||
bootstrap.group(group)
|
||||
.channel(NioSocketChannel.class)
|
||||
.handler(new ChannelInitializer<SocketChannel>() {
|
||||
@Override
|
||||
public void initChannel(SocketChannel ch) throws Exception {
|
||||
ChannelPipeline pipeline = ch.pipeline();
|
||||
if (sslCtx != null) {
|
||||
pipeline.addLast(sslCtx.newHandler(ch.alloc()));
|
||||
}
|
||||
pipeline.addLast("http-codec", new HttpClientCodec());
|
||||
pipeline.addLast("aggregator", new HttpObjectAggregator(65536));
|
||||
pipeline.addLast("ws-handler", webSocketClientHandler);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
public void open() throws Exception {
|
||||
//System.out.println("WebSocket Client connecting");
|
||||
webSocketClientHandler =
|
||||
new WebSocketClientHandler(
|
||||
WebSocketClientHandshakerFactory.newHandshaker(
|
||||
uri, WebSocketVersion.V13, null, false, EmptyHttpHeaders.INSTANCE, 1280000), this);
|
||||
ch = bootstrap.connect(uri.getHost(), uri.getPort()).sync().channel();
|
||||
webSocketClientHandler.handshakeFuture().sync();
|
||||
}
|
||||
public ChannelFuture send(String text)
|
||||
{
|
||||
LogHelper.dev("Send: %s", text);
|
||||
return ch.writeAndFlush(new TextWebSocketFrame(text));
|
||||
}
|
||||
abstract void onMessage(String message) throws Exception;
|
||||
abstract void onDisconnect() throws Exception;
|
||||
abstract void onOpen() throws Exception;
|
||||
|
||||
public void close() throws InterruptedException {
|
||||
//System.out.println("WebSocket Client sending close");
|
||||
isClosed = true;
|
||||
if(ch != null && ch.isActive())
|
||||
{
|
||||
ch.writeAndFlush(new CloseWebSocketFrame());
|
||||
ch.closeFuture().sync();
|
||||
}
|
||||
|
||||
//group.shutdownGracefully();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(int code, String reason, boolean remote) {
|
||||
LogHelper.debug("Disconnected: " + code + " " + remote + " " + reason != null ? reason : "no reason");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception ex) {
|
||||
LogHelper.error(ex);
|
||||
public void eval(final String text) throws IOException {
|
||||
ch.writeAndFlush(new TextWebSocketFrame(text));
|
||||
}
|
||||
|
||||
}
|
|
@ -2,7 +2,6 @@
|
|||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import org.java_websocket.handshake.ServerHandshake;
|
||||
import ru.gravit.launcher.events.ExceptionEvent;
|
||||
import ru.gravit.launcher.events.request.*;
|
||||
import ru.gravit.launcher.hasher.HashedEntry;
|
||||
|
@ -10,10 +9,10 @@
|
|||
import ru.gravit.launcher.request.ResultInterface;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Type;
|
||||
import java.net.URI;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
||||
|
@ -27,8 +26,8 @@ public class ClientWebSocketService extends ClientJSONPoint {
|
|||
private HashMap<String, Class<? extends ResultInterface>> results;
|
||||
private HashSet<EventHandler> handlers;
|
||||
|
||||
public ClientWebSocketService(GsonBuilder gsonBuilder, String address, int i) {
|
||||
super(createURL(address), Collections.emptyMap(), i);
|
||||
public ClientWebSocketService(GsonBuilder gsonBuilder, String address, int i) throws SSLException {
|
||||
super(createURL(address));
|
||||
requests = new HashMap<>();
|
||||
results = new HashMap<>();
|
||||
handlers = new HashSet<>();
|
||||
|
@ -51,7 +50,7 @@ private static URI createURL(String address) {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
void onMessage(String message) {
|
||||
ResultInterface result = gson.fromJson(message, ResultInterface.class);
|
||||
for (EventHandler handler : handlers) {
|
||||
handler.process(result);
|
||||
|
@ -59,25 +58,19 @@ public void onMessage(String message) {
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception e) {
|
||||
LogHelper.error(e);
|
||||
void onDisconnect() {
|
||||
LogHelper.info("WebSocket client disconnect");
|
||||
if(onCloseCallback != null) onCloseCallback.onClose(0,"unsupported param", !isClosed);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(ServerHandshake handshakedata) {
|
||||
//Notify open
|
||||
void onOpen() throws Exception {
|
||||
synchronized (onConnect)
|
||||
{
|
||||
onConnect.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClose(int code, String reason, boolean remote)
|
||||
{
|
||||
LogHelper.debug("Disconnected: " + code + " " + remote + " " + (reason != null ? reason : "no reason"));
|
||||
if(onCloseCallback != null)
|
||||
onCloseCallback.onClose(code, reason, remote);
|
||||
}
|
||||
@FunctionalInterface
|
||||
public interface OnCloseCallback
|
||||
{
|
||||
|
@ -136,7 +129,7 @@ public void registerHandler(EventHandler eventHandler) {
|
|||
}
|
||||
public void waitIfNotConnected()
|
||||
{
|
||||
if(!isOpen() && !isClosed() && !isClosing())
|
||||
/*if(!isOpen() && !isClosed() && !isClosing())
|
||||
{
|
||||
LogHelper.warning("WebSocket not connected. Try wait onConnect object");
|
||||
synchronized (onConnect)
|
||||
|
@ -147,20 +140,22 @@ public void waitIfNotConnected()
|
|||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
public void sendObject(Object obj) throws IOException {
|
||||
waitIfNotConnected();
|
||||
if(isClosed() && reconnectCallback != null)
|
||||
reconnectCallback.onReconnect();
|
||||
if(ch == null || !ch.isActive()) reconnectCallback.onReconnect();
|
||||
//if(isClosed() && reconnectCallback != null)
|
||||
// reconnectCallback.onReconnect();
|
||||
send(gson.toJson(obj, RequestInterface.class));
|
||||
}
|
||||
|
||||
public void sendObject(Object obj, Type type) throws IOException {
|
||||
waitIfNotConnected();
|
||||
if(isClosed() && reconnectCallback != null)
|
||||
reconnectCallback.onReconnect();
|
||||
if(ch == null || !ch.isActive()) reconnectCallback.onReconnect();
|
||||
//if(isClosed() && reconnectCallback != null)
|
||||
// reconnectCallback.onReconnect();
|
||||
send(gson.toJson(obj, type));
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
import ru.gravit.utils.helper.JVMHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import javax.net.ssl.SSLException;
|
||||
import java.io.IOException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
@ -15,7 +16,7 @@
|
|||
|
||||
public class StandartClientWebSocketService extends ClientWebSocketService {
|
||||
public WaitEventHandler waitEventHandler = new WaitEventHandler();
|
||||
public StandartClientWebSocketService(GsonBuilder gsonBuilder, String address, int i) {
|
||||
public StandartClientWebSocketService(GsonBuilder gsonBuilder, String address, int i) throws SSLException {
|
||||
super(gsonBuilder, address, i);
|
||||
}
|
||||
public class RequestFuture implements Future<ResultInterface>
|
||||
|
@ -101,27 +102,38 @@ public RequestFuture asyncSendRequest(RequestInterface request) throws IOExcepti
|
|||
}
|
||||
|
||||
public static StandartClientWebSocketService initWebSockets(String address, boolean async) {
|
||||
StandartClientWebSocketService service = new StandartClientWebSocketService(new GsonBuilder(), address, 5000);
|
||||
StandartClientWebSocketService service;
|
||||
try {
|
||||
service = new StandartClientWebSocketService(new GsonBuilder(), address, 5000);
|
||||
} catch (SSLException e) {
|
||||
LogHelper.error(e);
|
||||
return null;
|
||||
}
|
||||
service.registerResults();
|
||||
service.registerRequests();
|
||||
service.registerHandler(service.waitEventHandler);
|
||||
if(!async)
|
||||
{
|
||||
try {
|
||||
if (!service.connectBlocking()) LogHelper.error("Error connecting");
|
||||
service.open();
|
||||
LogHelper.debug("Connect to %s", address);
|
||||
} catch (InterruptedException e) {
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
service.connect();
|
||||
try {
|
||||
service.open();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
JVMHelper.RUNTIME.addShutdownHook(new Thread(() -> {
|
||||
try {
|
||||
if(service.isOpen())
|
||||
service.closeBlocking();
|
||||
//if(service.isOpen())
|
||||
// service.closeBlocking();
|
||||
service.close();
|
||||
} catch (InterruptedException e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
package ru.gravit.launcher.request.websockets;
|
||||
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelFuture;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.channel.ChannelPromise;
|
||||
import io.netty.channel.SimpleChannelInboundHandler;
|
||||
import io.netty.handler.codec.http.FullHttpResponse;
|
||||
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.PongWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
|
||||
import io.netty.handler.codec.http.websocketx.WebSocketFrame;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object> {
|
||||
|
||||
private final WebSocketClientHandshaker handshaker;
|
||||
private final ClientJSONPoint clientJSONPoint;
|
||||
private ChannelPromise handshakeFuture;
|
||||
|
||||
public WebSocketClientHandler(final WebSocketClientHandshaker handshaker, ClientJSONPoint clientJSONPoint) {
|
||||
this.handshaker = handshaker;
|
||||
this.clientJSONPoint = clientJSONPoint;
|
||||
}
|
||||
|
||||
public ChannelFuture handshakeFuture() {
|
||||
return handshakeFuture;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handlerAdded(final ChannelHandlerContext ctx) throws Exception {
|
||||
handshakeFuture = ctx.newPromise();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelActive(final ChannelHandlerContext ctx) throws Exception {
|
||||
handshaker.handshake(ctx.channel());
|
||||
clientJSONPoint.onOpen();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void channelInactive(final ChannelHandlerContext ctx) throws Exception {
|
||||
//System.out.println("WebSocket Client disconnected!");
|
||||
clientJSONPoint.onDisconnect();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
|
||||
final Channel ch = ctx.channel();
|
||||
if (!handshaker.isHandshakeComplete()) {
|
||||
// web socket client connected
|
||||
handshaker.finishHandshake(ch, (FullHttpResponse) msg);
|
||||
handshakeFuture.setSuccess();
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg instanceof FullHttpResponse) {
|
||||
final FullHttpResponse response = (FullHttpResponse) msg;
|
||||
throw new Exception("Unexpected FullHttpResponse (getStatus=" + response.status() + ", content="
|
||||
+ response.content().toString(CharsetUtil.UTF_8) + ')');
|
||||
}
|
||||
|
||||
final WebSocketFrame frame = (WebSocketFrame) msg;
|
||||
if (frame instanceof TextWebSocketFrame) {
|
||||
final TextWebSocketFrame textFrame = (TextWebSocketFrame) frame;
|
||||
clientJSONPoint.onMessage(textFrame.text());
|
||||
LogHelper.dev("Message: %s", textFrame.text());
|
||||
// uncomment to print request
|
||||
// logger.info(textFrame.text());
|
||||
} else if (frame instanceof PongWebSocketFrame) {
|
||||
} else if (frame instanceof CloseWebSocketFrame)
|
||||
ch.close();
|
||||
else if (frame instanceof BinaryWebSocketFrame) {
|
||||
// uncomment to print request
|
||||
// logger.info(frame.content().toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exceptionCaught(final ChannelHandlerContext ctx, final Throwable cause) throws Exception {
|
||||
LogHelper.error(cause);
|
||||
|
||||
if (!handshakeFuture.isDone()) {
|
||||
handshakeFuture.setFailure(cause);
|
||||
}
|
||||
|
||||
ctx.close();
|
||||
}
|
||||
}
|
|
@ -2,7 +2,8 @@
|
|||
* Discord channel: https://discord.gg/aJK6nMN
|
||||
* [See license](LICENSE)
|
||||
* [See code of conduct](CODE_OF_CONDUCT.md)
|
||||
* [WIKI](https://launcher.gravit.pro)
|
||||
* [WIKI](https://yii2.gravit.pro)
|
||||
* [OLD WIKI (4.X.X)](https://launcher.gravit.pro)
|
||||
* Get it (requires cURL):
|
||||
```sh
|
||||
curl -s https://raw.githubusercontent.com/GravitLauncher/Launcher/master/get_it.sh | sh
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
apply plugin: 'com.github.johnrengelman.shadow'
|
||||
|
||||
String mainClassName = "ru.gravit.launcher.server.ServerWrapper"
|
||||
String mainAgentName = "ru.gravit.launcher.server.ServerAgent"
|
||||
|
||||
configurations {
|
||||
pack
|
||||
compile.extendsFrom pack
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
|
@ -12,6 +18,7 @@
|
|||
targetCompatibility = '1.8'
|
||||
|
||||
jar {
|
||||
classifier = 'clean'
|
||||
from { configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } }
|
||||
manifest.attributes("Main-Class": mainClassName,
|
||||
"Premain-Class": mainAgentName,
|
||||
|
@ -21,5 +28,18 @@
|
|||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':LauncherAPI')
|
||||
pack project(':LauncherAPI')
|
||||
pack 'org.apache.httpcomponents:httpclient:4.5.7'
|
||||
pack 'io.netty:netty-all:4.1.32.Final'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
classifier = null
|
||||
relocate 'io.netty', 'ru.gravit.repackage.io.netty'
|
||||
configurations = [project.configurations.pack]
|
||||
exclude 'module-info.class'
|
||||
}
|
||||
|
||||
|
||||
build.dependsOn tasks.shadowJar
|
||||
|
|
@ -6,6 +6,7 @@
|
|||
import ru.gravit.launcher.events.request.ProfilesRequestEvent;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.request.Request;
|
||||
import ru.gravit.launcher.request.RequestException;
|
||||
import ru.gravit.launcher.request.auth.AuthRequest;
|
||||
import ru.gravit.launcher.request.update.ProfilesRequest;
|
||||
import ru.gravit.launcher.server.setup.ServerWrapperSetup;
|
||||
|
@ -162,15 +163,16 @@ public void run(String... args) throws Throwable {
|
|||
{
|
||||
LogHelper.debug("WebSocket connect closed. Try reconnect");
|
||||
try {
|
||||
if (!Request.service.reconnectBlocking()) LogHelper.error("Error connecting");
|
||||
Request.service.open();
|
||||
LogHelper.debug("Connect to %s", config.websocket.address);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
throw new RequestException(String.format("Connect error: %s", e.getMessage() != null ? e.getMessage() : "null"));
|
||||
}
|
||||
auth();
|
||||
};
|
||||
}
|
||||
LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s port %d. Title: %s", config.projectname, config.websocket.address, config.title);
|
||||
LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s. Title: %s", config.projectname, config.websocket.address, config.title);
|
||||
LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name);
|
||||
LogHelper.info("Start Minecraft Server");
|
||||
LogHelper.debug("Invoke main method %s", mainClass.getName());
|
||||
|
|
|
@ -67,6 +67,7 @@ public void run() throws IOException {
|
|||
wrapper.config.password = password;
|
||||
wrapper.config.title = title;
|
||||
wrapper.config.stopOnError = false;
|
||||
wrapper.updateLauncherConfig();
|
||||
|
||||
if (wrapper.auth()) {
|
||||
break;
|
||||
|
|
|
@ -60,7 +60,7 @@ public final class Launcher {
|
|||
public static final int MAJOR = 5;
|
||||
public static final int MINOR = 0;
|
||||
public static final int PATCH = 0;
|
||||
public static final int BUILD = 2;
|
||||
public static final int BUILD = 3;
|
||||
public static final Version.Type RELEASE = Version.Type.BETA;
|
||||
public static GsonManager gsonManager;
|
||||
|
||||
|
|
|
@ -27,7 +27,8 @@ public enum Version {
|
|||
MC1122("1.12.2", 340),
|
||||
MC113("1.13", 393),
|
||||
MC1131("1.13.1", 401),
|
||||
MC1132("1.13.2", 402);
|
||||
MC1132("1.13.2", 402),
|
||||
MC114("1.14", 477);
|
||||
private static final Map<String, Version> VERSIONS;
|
||||
|
||||
static {
|
||||
|
|
|
@ -6,8 +6,6 @@
|
|||
public class LauncherSSLContext {
|
||||
public SSLServerSocketFactory ssf;
|
||||
public SSLSocketFactory sf;
|
||||
@SuppressWarnings("unused")
|
||||
private SSLContext sc;
|
||||
|
||||
public LauncherSSLContext(KeyStore ks, String keypassword) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, KeyManagementException {
|
||||
TrustManager[] trustAllCerts = new TrustManager[]{
|
||||
|
|
|
@ -1,213 +0,0 @@
|
|||
package ru.gravit.utils.downloader;
|
||||
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.net.HttpURLConnection;
|
||||
import java.net.URL;
|
||||
import java.security.cert.Certificate;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class Downloader implements Runnable {
|
||||
@FunctionalInterface
|
||||
public interface Handler {
|
||||
void check(Certificate[] certs) throws IOException;
|
||||
}
|
||||
|
||||
public static final Map<String, String> requestClient = Collections.singletonMap("User-Agent",
|
||||
"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.95 Safari/537.11");
|
||||
public static final int INTERVAL = 300;
|
||||
|
||||
private final File file;
|
||||
private final URL url;
|
||||
private final String method;
|
||||
public final Map<String, String> requestProps;
|
||||
public AtomicInteger writed = new AtomicInteger(0);
|
||||
public final AtomicBoolean interrupt = new AtomicBoolean(false);
|
||||
public final AtomicBoolean interrupted = new AtomicBoolean(false);
|
||||
public AtomicReference<Throwable> ex = new AtomicReference<>(null);
|
||||
private final int skip;
|
||||
private final Handler handler;
|
||||
|
||||
private HttpURLConnection connect = null;
|
||||
|
||||
public Downloader(URL url, File file) {
|
||||
this.requestProps = new HashMap<>(requestClient);
|
||||
this.file = file;
|
||||
this.url = url;
|
||||
this.skip = 0;
|
||||
this.handler = null;
|
||||
this.method = null;
|
||||
}
|
||||
|
||||
public Downloader(URL url, File file, int skip) {
|
||||
this.requestProps = new HashMap<>(requestClient);
|
||||
this.file = file;
|
||||
this.url = url;
|
||||
this.skip = skip;
|
||||
this.handler = null;
|
||||
this.method = null;
|
||||
}
|
||||
|
||||
public Downloader(URL url, File file, Handler handler) {
|
||||
this.requestProps = new HashMap<>(requestClient);
|
||||
this.file = file;
|
||||
this.url = url;
|
||||
this.skip = 0;
|
||||
this.handler = handler;
|
||||
this.method = null;
|
||||
}
|
||||
|
||||
public Downloader(URL url, File file, int skip, Handler handler) {
|
||||
this.requestProps = new HashMap<>(requestClient);
|
||||
this.file = file;
|
||||
this.url = url;
|
||||
this.skip = skip;
|
||||
this.handler = handler;
|
||||
this.method = null;
|
||||
}
|
||||
|
||||
public Downloader(URL url, File file, int skip, Handler handler, Map<String, String> requestProps) {
|
||||
this.requestProps = new HashMap<>(requestProps);
|
||||
this.file = file;
|
||||
this.url = url;
|
||||
this.skip = skip;
|
||||
this.handler = handler;
|
||||
this.method = null;
|
||||
}
|
||||
|
||||
public Downloader(URL url, File file, int skip, Handler handler, Map<String, String> requestProps, String method) {
|
||||
this.requestProps = new HashMap<>(requestProps);
|
||||
this.file = file;
|
||||
this.url = url;
|
||||
this.skip = skip;
|
||||
this.handler = handler;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public Downloader(URL url, File file, int skip, Handler handler, String method) {
|
||||
this.requestProps = new HashMap<>(requestClient);
|
||||
this.file = file;
|
||||
this.url = url;
|
||||
this.skip = skip;
|
||||
this.handler = handler;
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public Map<String, String> getProps() {
|
||||
return requestProps;
|
||||
}
|
||||
|
||||
public void addProp(String key, String value) {
|
||||
requestProps.put(key, value);
|
||||
}
|
||||
|
||||
public File getFile() {
|
||||
return file;
|
||||
}
|
||||
|
||||
public String getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public Handler getHandler() {
|
||||
return handler;
|
||||
}
|
||||
|
||||
public void downloadFile() throws IOException {
|
||||
if (!(url.getProtocol().equalsIgnoreCase("http") || url.getProtocol().equalsIgnoreCase("https")))
|
||||
throw new IOException("Invalid protocol.");
|
||||
interrupted.set(false);
|
||||
if (url.getProtocol().equalsIgnoreCase("http")) {
|
||||
HttpURLConnection connect = (HttpURLConnection) (url).openConnection();
|
||||
this.connect = connect;
|
||||
if (method != null) connect.setRequestMethod(method);
|
||||
for (Map.Entry<String, String> ent : requestProps.entrySet()) {
|
||||
connect.setRequestProperty(ent.getKey(), ent.getValue());
|
||||
}
|
||||
connect.setInstanceFollowRedirects(true);
|
||||
if (!(connect.getResponseCode() >= 200 && connect.getResponseCode() < 300))
|
||||
throw new IOException(String.format("Invalid response of http server %d.", connect.getResponseCode()));
|
||||
try (BufferedInputStream in = new BufferedInputStream(connect.getInputStream(), IOHelper.BUFFER_SIZE);
|
||||
FileOutputStream fout = new FileOutputStream(file, skip != 0)) {
|
||||
byte data[] = new byte[IOHelper.BUFFER_SIZE];
|
||||
int count = -1;
|
||||
long timestamp = System.currentTimeMillis();
|
||||
int writed_local = 0;
|
||||
in.skip(skip);
|
||||
while ((count = in.read(data)) != -1) {
|
||||
fout.write(data, 0, count);
|
||||
writed_local += count;
|
||||
if (System.currentTimeMillis() - timestamp > INTERVAL) {
|
||||
writed.set(writed_local);
|
||||
LogHelper.debug("Downloaded %d", writed_local);
|
||||
if (interrupt.get()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
LogHelper.debug("Downloaded %d", writed_local);
|
||||
writed.set(writed_local);
|
||||
}
|
||||
} else {
|
||||
HttpsURLConnection connect = (HttpsURLConnection) (url).openConnection();
|
||||
this.connect = connect;
|
||||
if (method != null) connect.setRequestMethod(method);
|
||||
for (Map.Entry<String, String> ent : requestProps.entrySet()) {
|
||||
connect.setRequestProperty(ent.getKey(), ent.getValue());
|
||||
}
|
||||
connect.setInstanceFollowRedirects(true);
|
||||
if (handler != null)
|
||||
handler.check(connect.getServerCertificates());
|
||||
if (!(connect.getResponseCode() >= 200 && connect.getResponseCode() < 300))
|
||||
throw new IOException(String.format("Invalid response of http server %d.", connect.getResponseCode()));
|
||||
try (BufferedInputStream in = new BufferedInputStream(connect.getInputStream(), IOHelper.BUFFER_SIZE);
|
||||
FileOutputStream fout = new FileOutputStream(file, skip != 0)) {
|
||||
byte data[] = new byte[IOHelper.BUFFER_SIZE];
|
||||
int count = -1;
|
||||
long timestamp = System.currentTimeMillis();
|
||||
int writed_local = 0;
|
||||
in.skip(skip);
|
||||
while ((count = in.read(data)) != -1) {
|
||||
fout.write(data, 0, count);
|
||||
writed_local += count;
|
||||
if (System.currentTimeMillis() - timestamp > INTERVAL) {
|
||||
writed.set(writed_local);
|
||||
LogHelper.debug("Downloaded %d", writed_local);
|
||||
if (interrupt.get()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
LogHelper.debug("Downloaded %d", writed_local);
|
||||
writed.set(writed_local);
|
||||
}
|
||||
}
|
||||
interrupted.set(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
downloadFile();
|
||||
} catch (Throwable ex) {
|
||||
this.ex.set(ex);
|
||||
LogHelper.error(ex);
|
||||
}
|
||||
if (connect != null)
|
||||
try {
|
||||
connect.disconnect();
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,8 +7,6 @@
|
|||
import java.lang.management.ManagementFactory;
|
||||
import java.lang.management.OperatingSystemMXBean;
|
||||
import java.lang.management.RuntimeMXBean;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
|
@ -52,8 +50,6 @@ public static OS byName(String name) {
|
|||
public static final int OS_BITS = getCorrectOSArch();
|
||||
@LauncherAPI
|
||||
public static final int JVM_BITS = Integer.parseInt(System.getProperty("sun.arch.data.model"));
|
||||
@LauncherAPI
|
||||
public static final int RAM = getRAMAmount();
|
||||
|
||||
@LauncherAPI
|
||||
public static final SecurityManager SECURITY_MANAGER = System.getSecurityManager();
|
||||
|
@ -137,19 +133,6 @@ public static String getEnvPropertyCaseSensitive(String name) {
|
|||
return System.getenv().get(name);
|
||||
}
|
||||
|
||||
private static int getRAMAmount() {
|
||||
int physicalRam = 1024;
|
||||
try {
|
||||
final Method getTotalPhysicalMemorySize = OPERATING_SYSTEM_MXBEAN.getClass().getDeclaredMethod("getTotalPhysicalMemorySize");
|
||||
getTotalPhysicalMemorySize.setAccessible(true);
|
||||
physicalRam = (int) ((long)getTotalPhysicalMemorySize.invoke(OPERATING_SYSTEM_MXBEAN) >> 20);
|
||||
} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException | NoSuchMethodException
|
||||
| SecurityException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
return Math.min(physicalRam, OS_BITS == 32 ? 1536 : 32768); // Limit 32-bit OS to 1536 MiB, and 64-bit OS to 32768 MiB (because it's enough)
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static boolean isJVMMatchesSystemArch() {
|
||||
return JVM_BITS == OS_BITS;
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public final class LogHelper {
|
||||
|
@ -50,6 +51,7 @@ public enum OutputTypes {
|
|||
}
|
||||
|
||||
private static final Set<OutputEnity> OUTPUTS = Collections.newSetFromMap(new ConcurrentHashMap<>(2));
|
||||
private static final Set<Consumer<Throwable>> EXCEPTIONS_CALLBACKS = Collections.newSetFromMap(new ConcurrentHashMap<>(2));
|
||||
private static final OutputEnity STD_OUTPUT;
|
||||
|
||||
private LogHelper() {
|
||||
|
@ -60,6 +62,11 @@ public static void addOutput(OutputEnity output) {
|
|||
OUTPUTS.add(Objects.requireNonNull(output, "output"));
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void addExcCallback(Consumer<Throwable> output) {
|
||||
EXCEPTIONS_CALLBACKS.add(Objects.requireNonNull(output, "output"));
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void addOutput(Output output, OutputTypes type) {
|
||||
OUTPUTS.add(new OutputEnity(Objects.requireNonNull(output, "output"), type));
|
||||
|
@ -105,6 +112,7 @@ public static void dev(String format, Object... args) {
|
|||
|
||||
@LauncherAPI
|
||||
public static void error(Throwable exc) {
|
||||
EXCEPTIONS_CALLBACKS.forEach(e -> e.accept(exc));
|
||||
error(isStacktraceEnabled() ? toString(exc) : exc.toString());
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue