mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 11:39:11 +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;
|
package ru.gravit.launchserver;
|
||||||
|
|
||||||
|
import io.netty.handler.logging.LogLevel;
|
||||||
import ru.gravit.launcher.Launcher;
|
import ru.gravit.launcher.Launcher;
|
||||||
import ru.gravit.launcher.LauncherConfig;
|
import ru.gravit.launcher.LauncherConfig;
|
||||||
import ru.gravit.launcher.NeedGarbageCollection;
|
import ru.gravit.launcher.NeedGarbageCollection;
|
||||||
|
@ -80,6 +81,8 @@ public static final class Config {
|
||||||
|
|
||||||
public String binaryName;
|
public String binaryName;
|
||||||
|
|
||||||
|
public boolean copyBinaries = true;
|
||||||
|
|
||||||
public LauncherConfig.LauncherEnvironment env;
|
public LauncherConfig.LauncherEnvironment env;
|
||||||
|
|
||||||
// Handlers & Providers
|
// Handlers & Providers
|
||||||
|
@ -269,7 +272,7 @@ public class LauncherConf
|
||||||
}
|
}
|
||||||
|
|
||||||
public class NettyConfig {
|
public class NettyConfig {
|
||||||
public boolean clientEnabled;
|
public boolean fileServerEnabled;
|
||||||
public boolean sendExceptionEnabled;
|
public boolean sendExceptionEnabled;
|
||||||
public String launcherURL;
|
public String launcherURL;
|
||||||
public String downloadURL;
|
public String downloadURL;
|
||||||
|
@ -278,6 +281,7 @@ public class NettyConfig {
|
||||||
public Map<String, String> bindings = new HashMap<>();
|
public Map<String, String> bindings = new HashMap<>();
|
||||||
public NettyPerformanceConfig performance;
|
public NettyPerformanceConfig performance;
|
||||||
public NettyBindAddress[] binds;
|
public NettyBindAddress[] binds;
|
||||||
|
public LogLevel logLevel = LogLevel.DEBUG;
|
||||||
}
|
}
|
||||||
public class NettyPerformanceConfig
|
public class NettyPerformanceConfig
|
||||||
{
|
{
|
||||||
|
@ -678,6 +682,7 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
||||||
Config newConfig = new Config();
|
Config newConfig = new Config();
|
||||||
newConfig.mirrors = new String[]{"http://mirror.gravitlauncher.ml/", "https://mirror.gravit.pro/"};
|
newConfig.mirrors = new String[]{"http://mirror.gravitlauncher.ml/", "https://mirror.gravit.pro/"};
|
||||||
newConfig.launch4j = new ExeConf();
|
newConfig.launch4j = new ExeConf();
|
||||||
|
newConfig.launch4j.enabled = true;
|
||||||
newConfig.launch4j.copyright = "© GravitLauncher Team";
|
newConfig.launch4j.copyright = "© GravitLauncher Team";
|
||||||
newConfig.launch4j.fileDesc = "GravitLauncher ".concat(Launcher.getVersion().getVersionString());
|
newConfig.launch4j.fileDesc = "GravitLauncher ".concat(Launcher.getVersion().getVersionString());
|
||||||
newConfig.launch4j.fileVer = Launcher.getVersion().getVersionString().concat(".").concat(String.valueOf(Launcher.getVersion().patch));
|
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.whitelistRejectString = "Вас нет в белом списке";
|
||||||
|
|
||||||
newConfig.netty = new NettyConfig();
|
newConfig.netty = new NettyConfig();
|
||||||
newConfig.netty.address = "ws://localhost:9274/api";
|
newConfig.netty.fileServerEnabled = true;
|
||||||
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.binds = new NettyBindAddress[]{ new NettyBindAddress("0.0.0.0", 9274) };
|
newConfig.netty.binds = new NettyBindAddress[]{ new NettyBindAddress("0.0.0.0", 9274) };
|
||||||
newConfig.netty.performance = new NettyPerformanceConfig();
|
newConfig.netty.performance = new NettyPerformanceConfig();
|
||||||
newConfig.netty.performance.bossThread = 2;
|
newConfig.netty.performance.bossThread = 2;
|
||||||
|
@ -720,7 +721,7 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
||||||
newConfig.threadCoreCount = 0; // on your own
|
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.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.enabledProGuard = true;
|
||||||
newConfig.stripLineNumbers = true;
|
newConfig.stripLineNumbers = true;
|
||||||
newConfig.deleteTempFiles = true;
|
newConfig.deleteTempFiles = true;
|
||||||
|
@ -734,19 +735,20 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
||||||
newConfig.components.put("authLimiter", authLimiterComponent);
|
newConfig.components.put("authLimiter", authLimiterComponent);
|
||||||
|
|
||||||
// Set server address
|
// Set server address
|
||||||
|
String address;
|
||||||
if (testEnv) {
|
if (testEnv) {
|
||||||
newConfig.setLegacyAddress("localhost");
|
address = "localhost";
|
||||||
newConfig.setProjectName("test");
|
newConfig.setProjectName("test");
|
||||||
} else {
|
} else {
|
||||||
System.out.println("LaunchServer legacy address(default: localhost): ");
|
System.out.println("LaunchServer address(default: localhost): ");
|
||||||
newConfig.setLegacyAddress(commandHandler.readLine());
|
address = commandHandler.readLine();
|
||||||
System.out.println("LaunchServer projectName: ");
|
System.out.println("LaunchServer projectName: ");
|
||||||
newConfig.setProjectName(commandHandler.readLine());
|
newConfig.setProjectName(commandHandler.readLine());
|
||||||
}
|
}
|
||||||
if(newConfig.legacyAddress == null)
|
if(address == null)
|
||||||
{
|
{
|
||||||
LogHelper.error("Legacy address null. Using localhost");
|
LogHelper.error("Address null. Using localhost");
|
||||||
newConfig.legacyAddress = "localhost";
|
address = "localhost";
|
||||||
}
|
}
|
||||||
if(newConfig.projectName == null)
|
if(newConfig.projectName == null)
|
||||||
{
|
{
|
||||||
|
@ -754,6 +756,13 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
||||||
newConfig.projectName = "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
|
// Write LaunchServer config
|
||||||
LogHelper.info("Writing LaunchServer config file");
|
LogHelper.info("Writing LaunchServer config file");
|
||||||
try (BufferedWriter writer = IOHelper.newWriter(configFile)) {
|
try (BufferedWriter writer = IOHelper.newWriter(configFile)) {
|
||||||
|
@ -836,14 +845,14 @@ public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
||||||
LogHelper.info("Syncing updates dir");
|
LogHelper.info("Syncing updates dir");
|
||||||
Map<String, SignedObjectHolder<HashedDir>> newUpdatesDirMap = new HashMap<>(16);
|
Map<String, SignedObjectHolder<HashedDir>> newUpdatesDirMap = new HashMap<>(16);
|
||||||
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(updatesDir)) {
|
try (DirectoryStream<Path> dirStream = Files.newDirectoryStream(updatesDir)) {
|
||||||
for (Path updateDir : dirStream) {
|
for (final Path updateDir : dirStream) {
|
||||||
if (Files.isHidden(updateDir))
|
if (Files.isHidden(updateDir))
|
||||||
continue; // Skip hidden
|
continue; // Skip hidden
|
||||||
|
|
||||||
// Resolve name and verify is dir
|
// Resolve name and verify is dir
|
||||||
String name = IOHelper.getFileName(updateDir);
|
String name = IOHelper.getFileName(updateDir);
|
||||||
if (!IOHelper.isDir(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;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ public void clear() {
|
||||||
|
|
||||||
|
|
||||||
public EXEL4JLauncherBinary(LaunchServer server) {
|
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");
|
faviconFile = server.dir.resolve("favicon.ico");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
public class EXELauncherBinary extends LauncherBinary {
|
public class EXELauncherBinary extends LauncherBinary {
|
||||||
|
|
||||||
public EXELauncherBinary(LaunchServer server) {
|
public EXELauncherBinary(LaunchServer server) {
|
||||||
super(server, server.dir.resolve(server.config.binaryName + ".exe"));
|
super(server, LauncherBinary.resolve(server, ".exe"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -24,9 +24,8 @@ public final class JARLauncherBinary extends LauncherBinary {
|
||||||
public List<Path> addonLibs;
|
public List<Path> addonLibs;
|
||||||
|
|
||||||
public JARLauncherBinary(LaunchServer server) throws IOException {
|
public JARLauncherBinary(LaunchServer server) throws IOException {
|
||||||
super(server);
|
super(server, LauncherBinary.resolve(server, ".jar"));
|
||||||
count = new AtomicLong(0);
|
count = new AtomicLong(0);
|
||||||
syncBinaryFile = server.dir.resolve(server.config.binaryName + ".jar");
|
|
||||||
runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR);
|
runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR);
|
||||||
guardDir = server.dir.resolve(Launcher.GUARD_DIR);
|
guardDir = server.dir.resolve(Launcher.GUARD_DIR);
|
||||||
buildDir = server.dir.resolve("build");
|
buildDir = server.dir.resolve("build");
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
|
|
||||||
public abstract class LauncherBinary {
|
public abstract class LauncherBinary {
|
||||||
public final LaunchServer server;
|
public final LaunchServer server;
|
||||||
public Path syncBinaryFile;
|
public final Path syncBinaryFile;
|
||||||
private volatile DigestBytesHolder binary;
|
private volatile DigestBytesHolder binary;
|
||||||
private volatile byte[] sign;
|
private volatile byte[] sign;
|
||||||
|
|
||||||
|
@ -19,10 +19,6 @@ protected LauncherBinary(LaunchServer server, Path binaryFile) {
|
||||||
syncBinaryFile = binaryFile;
|
syncBinaryFile = binaryFile;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected LauncherBinary(LaunchServer server) {
|
|
||||||
this.server = server;
|
|
||||||
}
|
|
||||||
|
|
||||||
public abstract void build() throws IOException;
|
public abstract void build() throws IOException;
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,4 +45,8 @@ public final boolean sync() throws IOException {
|
||||||
|
|
||||||
return exists;
|
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 = new ServerBootstrap();
|
||||||
serverBootstrap.group(bossGroup, workerGroup)
|
serverBootstrap.group(bossGroup, workerGroup)
|
||||||
.channel(NioServerSocketChannel.class)
|
.channel(NioServerSocketChannel.class)
|
||||||
.handler(new LoggingHandler(LogLevel.DEBUG))
|
.handler(new LoggingHandler(config.logLevel))
|
||||||
.childHandler(new ChannelInitializer<NioSocketChannel>() {
|
.childHandler(new ChannelInitializer<NioSocketChannel>() {
|
||||||
@Override
|
@Override
|
||||||
public void initChannel(NioSocketChannel ch) {
|
public void initChannel(NioSocketChannel ch) {
|
||||||
|
@ -42,7 +42,7 @@ public void initChannel(NioSocketChannel ch) {
|
||||||
pipeline.addLast(new HttpObjectAggregator(65536));
|
pipeline.addLast(new HttpObjectAggregator(65536));
|
||||||
pipeline.addLast(new WebSocketServerCompressionHandler());
|
pipeline.addLast(new WebSocketServerCompressionHandler());
|
||||||
pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
|
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());
|
pipeline.addLast(new WebSocketFrameHandler());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -60,7 +60,7 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
||||||
try {
|
try {
|
||||||
AuthRequestEvent result = new AuthRequestEvent();
|
AuthRequestEvent result = new AuthRequestEvent();
|
||||||
String ip = IOHelper.getIP(ctx.channel().remoteAddress());
|
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");
|
AuthProvider.authError("Don't skip Launcher Update");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
-keepattributes Signature
|
-keepattributes Signature
|
||||||
-adaptresourcefilecontents META-INF/MANIFEST.MF
|
-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 {
|
shadowJar {
|
||||||
classifier = null
|
classifier = null
|
||||||
relocate 'org.objectweb.asm', 'ru.gravit.repackage.org.objectweb.asm'
|
relocate 'org.objectweb.asm', 'ru.gravit.repackage.org.objectweb.asm'
|
||||||
|
relocate 'io.netty', 'ru.gravit.repackage.io.netty'
|
||||||
configurations = [project.configurations.pack]
|
configurations = [project.configurations.pack]
|
||||||
exclude 'module-info.class'
|
exclude 'module-info.class'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
pack project(':LauncherAPI') // Not error on obf.
|
pack project(':LauncherAPI')
|
||||||
bundle 'com.github.oshi:oshi-core:3.13.0'
|
bundle 'com.github.oshi:oshi-core:3.13.0'
|
||||||
bundle 'com.jfoenix:jfoenix:8.0.8'
|
bundle 'com.jfoenix:jfoenix:8.0.8'
|
||||||
bundle 'de.jensd:fontawesomefx:8.9'
|
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'
|
pack 'org.ow2.asm:asm-tree:7.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -59,6 +59,8 @@ function initLoginScene() {
|
||||||
savePasswordBox = pane.lookup("#rememberchb");
|
savePasswordBox = pane.lookup("#rememberchb");
|
||||||
savePasswordBox.setSelected(settings.login === null || settings.rsaPassword !== null);
|
savePasswordBox.setSelected(settings.login === null || settings.rsaPassword !== null);
|
||||||
|
|
||||||
|
authOptions = pane.lookup("#authOptions");
|
||||||
|
|
||||||
var link = pane.lookup("#link");
|
var link = pane.lookup("#link");
|
||||||
link.setText(config.linkText);
|
link.setText(config.linkText);
|
||||||
link.setOnAction(function(event) app.getHostServices().showDocument(config.linkURL.toURI()));
|
link.setOnAction(function(event) app.getHostServices().showDocument(config.linkURL.toURI()));
|
||||||
|
|
|
@ -42,7 +42,7 @@ var settingsOverlay = {
|
||||||
settingsOverlay.updateRAMLabel();
|
settingsOverlay.updateRAMLabel();
|
||||||
|
|
||||||
var ramSlider = holder.lookup("#ramSlider");
|
var ramSlider = holder.lookup("#ramSlider");
|
||||||
ramSlider.setMax(JVMHelper.RAM);
|
ramSlider.setMax(FunctionalBridge.getJVMTotalMemory());
|
||||||
ramSlider.setSnapToTicks(true);
|
ramSlider.setSnapToTicks(true);
|
||||||
ramSlider.setShowTickMarks(true);
|
ramSlider.setShowTickMarks(true);
|
||||||
ramSlider.setShowTickLabels(true);
|
ramSlider.setShowTickLabels(true);
|
||||||
|
|
|
@ -7,7 +7,8 @@
|
||||||
import org.objectweb.asm.tree.ClassNode;
|
import org.objectweb.asm.tree.ClassNode;
|
||||||
import org.objectweb.asm.tree.InsnNode;
|
import org.objectweb.asm.tree.InsnNode;
|
||||||
import org.objectweb.asm.tree.MethodNode;
|
import org.objectweb.asm.tree.MethodNode;
|
||||||
import ru.gravit.utils.NativeJVMHalt;
|
|
||||||
|
import ru.gravit.launcher.utils.NativeJVMHalt;
|
||||||
import ru.gravit.utils.helper.LogHelper;
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
|
@ -9,7 +9,8 @@
|
||||||
import ru.gravit.launcher.managers.ClientGsonManager;
|
import ru.gravit.launcher.managers.ClientGsonManager;
|
||||||
import ru.gravit.launcher.managers.ConsoleManager;
|
import ru.gravit.launcher.managers.ConsoleManager;
|
||||||
import ru.gravit.launcher.request.Request;
|
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.launcher.request.websockets.StandartClientWebSocketService;
|
||||||
import ru.gravit.utils.helper.CommonHelper;
|
import ru.gravit.utils.helper.CommonHelper;
|
||||||
import ru.gravit.utils.helper.EnvHelper;
|
import ru.gravit.utils.helper.EnvHelper;
|
||||||
|
@ -72,11 +73,28 @@ public void start(String... args) throws Throwable {
|
||||||
if (runtimeProvider == null) runtimeProvider = new JSRuntimeProvider();
|
if (runtimeProvider == null) runtimeProvider = new JSRuntimeProvider();
|
||||||
runtimeProvider.init(false);
|
runtimeProvider.init(false);
|
||||||
runtimeProvider.preLoad();
|
runtimeProvider.preLoad();
|
||||||
if(Request.service != null)
|
if(Request.service == null)
|
||||||
{
|
{
|
||||||
String address = Launcher.getConfig().address;
|
String address = Launcher.getConfig().address;
|
||||||
LogHelper.debug("Start async connection to %s", address);
|
LogHelper.debug("Start async connection to %s", address);
|
||||||
Request.service = StandartClientWebSocketService.initWebSockets(address, true);
|
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);
|
LauncherGuardManager.initGuard(false);
|
||||||
Objects.requireNonNull(args, "args");
|
Objects.requireNonNull(args, "args");
|
||||||
|
|
|
@ -3,17 +3,18 @@
|
||||||
import ru.gravit.launcher.*;
|
import ru.gravit.launcher.*;
|
||||||
import ru.gravit.launcher.guard.LauncherGuardManager;
|
import ru.gravit.launcher.guard.LauncherGuardManager;
|
||||||
import ru.gravit.launcher.gui.JSRuntimeProvider;
|
import ru.gravit.launcher.gui.JSRuntimeProvider;
|
||||||
import ru.gravit.launcher.hasher.DirWatcher;
|
|
||||||
import ru.gravit.launcher.hasher.FileNameMatcher;
|
import ru.gravit.launcher.hasher.FileNameMatcher;
|
||||||
import ru.gravit.launcher.hasher.HashedDir;
|
import ru.gravit.launcher.hasher.HashedDir;
|
||||||
import ru.gravit.launcher.managers.ClientGsonManager;
|
import ru.gravit.launcher.managers.ClientGsonManager;
|
||||||
import ru.gravit.launcher.profiles.ClientProfile;
|
import ru.gravit.launcher.profiles.ClientProfile;
|
||||||
import ru.gravit.launcher.profiles.PlayerProfile;
|
import ru.gravit.launcher.profiles.PlayerProfile;
|
||||||
import ru.gravit.launcher.request.Request;
|
import ru.gravit.launcher.request.Request;
|
||||||
|
import ru.gravit.launcher.request.RequestException;
|
||||||
import ru.gravit.launcher.request.auth.RestoreSessionRequest;
|
import ru.gravit.launcher.request.auth.RestoreSessionRequest;
|
||||||
import ru.gravit.launcher.serialize.HInput;
|
import ru.gravit.launcher.serialize.HInput;
|
||||||
import ru.gravit.launcher.serialize.HOutput;
|
import ru.gravit.launcher.serialize.HOutput;
|
||||||
import ru.gravit.launcher.serialize.stream.StreamObject;
|
import ru.gravit.launcher.serialize.stream.StreamObject;
|
||||||
|
import ru.gravit.launcher.utils.DirWatcher;
|
||||||
import ru.gravit.utils.PublicURLClassLoader;
|
import ru.gravit.utils.PublicURLClassLoader;
|
||||||
import ru.gravit.utils.helper.*;
|
import ru.gravit.utils.helper.*;
|
||||||
import ru.gravit.utils.helper.JVMHelper.OS;
|
import ru.gravit.utils.helper.JVMHelper.OS;
|
||||||
|
@ -36,7 +37,6 @@
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public final class ClientLauncher {
|
public final class ClientLauncher {
|
||||||
|
|
||||||
private static final class ClassPathFileVisitor extends SimpleFileVisitor<Path> {
|
private static final class ClassPathFileVisitor extends SimpleFileVisitor<Path> {
|
||||||
private final Collection<Path> result;
|
private final Collection<Path> result;
|
||||||
|
|
||||||
|
@ -328,7 +328,7 @@ public static Process launch(
|
||||||
context.playerProfile = params.pp;
|
context.playerProfile = params.pp;
|
||||||
context.args.add(javaBin.toString());
|
context.args.add(javaBin.toString());
|
||||||
context.args.add(MAGICAL_INTEL_OPTION);
|
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("-Xms" + params.ram + 'M');
|
||||||
context.args.add("-Xmx" + 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");
|
LogHelper.debug("WebSocket connect closed. Try reconnect");
|
||||||
try {
|
try {
|
||||||
if (!Request.service.reconnectBlocking()) LogHelper.error("Error connecting");
|
Request.service.open();
|
||||||
LogHelper.debug("Connect to %s", Launcher.getConfig().address);
|
LogHelper.debug("Connect to %s", Launcher.getConfig().address);
|
||||||
} catch (InterruptedException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
LogHelper.error(e);
|
||||||
|
throw new RequestException(String.format("Connect error: %s", e.getMessage() != null ? e.getMessage() : "null"));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
RestoreSessionRequest request1 = new RestoreSessionRequest(Request.getSession());
|
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)
|
// Hash directory and compare (ignore update-only matcher entries, it will break offline-mode)
|
||||||
HashedDir currentHDir = new HashedDir(dir, matcher, true, digest);
|
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)));
|
throw new SecurityException(String.format("Forbidden modification: '%s'", IOHelper.getFileName(dir)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private ClientLauncher() {
|
private ClientLauncher() {
|
||||||
|
|
|
@ -11,7 +11,6 @@
|
||||||
import ru.gravit.launcher.managers.HasherManager;
|
import ru.gravit.launcher.managers.HasherManager;
|
||||||
import ru.gravit.launcher.managers.HasherStore;
|
import ru.gravit.launcher.managers.HasherStore;
|
||||||
import ru.gravit.launcher.request.Request;
|
import ru.gravit.launcher.request.Request;
|
||||||
import ru.gravit.launcher.request.websockets.RequestInterface;
|
|
||||||
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||||
import ru.gravit.utils.helper.LogHelper;
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
@ -31,6 +30,8 @@ public class FunctionalBridge {
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static Thread getHWID = null;
|
public static Thread getHWID = null;
|
||||||
|
|
||||||
|
private static long cachedMemorySize = -1;
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static HashedDirRunnable offlineUpdateRequest(String dirName, Path dir, SignedObjectHolder<HashedDir> hdir, FileNameMatcher matcher, boolean digest) {
|
public static HashedDirRunnable offlineUpdateRequest(String dirName, Path dir, SignedObjectHolder<HashedDir> hdir, FileNameMatcher matcher, boolean digest) {
|
||||||
return () -> {
|
return () -> {
|
||||||
|
@ -42,11 +43,6 @@ public static HashedDirRunnable offlineUpdateRequest(String dirName, Path dir, S
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
|
||||||
public static void makeJsonRequest(RequestInterface request, Runnable callback) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static void startTask(Runnable task) {
|
public static void startTask(Runnable task) {
|
||||||
threadPool.execute(task);
|
threadPool.execute(task);
|
||||||
|
@ -60,8 +56,9 @@ public static HWID getHWID() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static long getTotalMemory() {
|
public static int getTotalMemory() {
|
||||||
return hwidProvider.getTotalMemory() >> 20;
|
if (cachedMemorySize > 0) return (int)cachedMemorySize;
|
||||||
|
return (int)(cachedMemorySize = hwidProvider.getTotalMemory() >> 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
|
@ -70,7 +67,7 @@ public static int getClientJVMBits() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static long getJVMTotalMemory() {
|
public static int getJVMTotalMemory() {
|
||||||
if (getClientJVMBits() == 32) {
|
if (getClientJVMBits() == 32) {
|
||||||
return Math.min(getTotalMemory(), 1536);
|
return Math.min(getTotalMemory(), 1536);
|
||||||
} else {
|
} else {
|
||||||
|
@ -106,6 +103,7 @@ public static void setAuthParams(AuthRequestEvent event) {
|
||||||
public interface HashedDirRunnable {
|
public interface HashedDirRunnable {
|
||||||
SignedObjectHolder<HashedDir> run() throws Exception;
|
SignedObjectHolder<HashedDir> run() throws Exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static void evalCommand(String cmd)
|
public static void evalCommand(String cmd)
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,7 +83,7 @@ public String getMacAddr() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public long getTotalMemory() {
|
public long getTotalMemory() {
|
||||||
if (noHWID) return -1;
|
if (noHWID) return 1024<<20;
|
||||||
if (hardware == null) hardware = systemInfo.getHardware();
|
if (hardware == null) hardware = systemInfo.getHardware();
|
||||||
return hardware.getMemory().getTotal();
|
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.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.launcher.hasher.HashedEntry.Type;
|
||||||
import ru.gravit.utils.NativeJVMHalt;
|
|
||||||
import ru.gravit.utils.helper.IOHelper;
|
import ru.gravit.utils.helper.IOHelper;
|
||||||
import ru.gravit.utils.helper.JVMHelper;
|
import ru.gravit.utils.helper.JVMHelper;
|
||||||
import ru.gravit.utils.helper.JVMHelper.OS;
|
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 cpw.mods.fml.SafeExitJVMLegacy;
|
||||||
import net.minecraftforge.fml.SafeExitJVM;
|
import net.minecraftforge.fml.SafeExitJVM;
|
|
@ -3,8 +3,8 @@
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':libLauncher')
|
compile project(':libLauncher')
|
||||||
compile 'org.java-websocket:Java-WebSocket:1.3.9'
|
compileOnly 'io.netty:netty-all:4.1.32.Final'
|
||||||
compile 'org.apache.httpcomponents:httpclient:4.5.7'
|
compileOnly 'org.apache.httpcomponents:httpclient:4.5.7'
|
||||||
compileOnly 'com.google.guava:guava:26.0-jre'
|
compileOnly 'com.google.guava:guava:26.0-jre'
|
||||||
compile files('../compat/authlib/authlib-clean.jar')
|
compile files('../compat/authlib/authlib-clean.jar')
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,11 +174,19 @@ public UpdateRequestEvent requestDo() throws Exception {
|
||||||
HashedDir.Diff diff = e.hdir.diff(localDir, matcher);
|
HashedDir.Diff diff = e.hdir.diff(localDir, matcher);
|
||||||
final List<ListDownloader.DownloadTask> adds = new ArrayList<>();
|
final List<ListDownloader.DownloadTask> adds = new ArrayList<>();
|
||||||
diff.mismatch.walk(IOHelper.CROSS_SEPARATOR, (path, name, entry) -> {
|
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;
|
HashedFile file = (HashedFile) entry;
|
||||||
totalSize += file.size;
|
totalSize += file.size;
|
||||||
adds.add(new ListDownloader.DownloadTask(path, 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();
|
totalSize = diff.mismatch.size();
|
||||||
startTime = Instant.now();
|
startTime = Instant.now();
|
||||||
|
|
|
@ -1,36 +1,101 @@
|
||||||
package ru.gravit.launcher.request.websockets;
|
package ru.gravit.launcher.request.websockets;
|
||||||
|
|
||||||
import org.java_websocket.client.WebSocketClient;
|
import io.netty.bootstrap.Bootstrap;
|
||||||
import org.java_websocket.drafts.Draft_6455;
|
import io.netty.channel.*;
|
||||||
import org.java_websocket.handshake.ServerHandshake;
|
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 ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
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) {
|
private final URI uri;
|
||||||
super(serverUri, new Draft_6455(), httpHeaders, connectTimeout);
|
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 ClientJSONPoint(URI uri) throws SSLException {
|
||||||
public void onOpen(ServerHandshake handshakedata) {
|
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 open() throws Exception {
|
||||||
public void onMessage(String message) {
|
//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 eval(final String text) throws IOException {
|
||||||
public void onClose(int code, String reason, boolean remote) {
|
ch.writeAndFlush(new TextWebSocketFrame(text));
|
||||||
LogHelper.debug("Disconnected: " + code + " " + remote + " " + reason != null ? reason : "no reason");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Exception ex) {
|
|
||||||
LogHelper.error(ex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import org.java_websocket.handshake.ServerHandshake;
|
|
||||||
import ru.gravit.launcher.events.ExceptionEvent;
|
import ru.gravit.launcher.events.ExceptionEvent;
|
||||||
import ru.gravit.launcher.events.request.*;
|
import ru.gravit.launcher.events.request.*;
|
||||||
import ru.gravit.launcher.hasher.HashedEntry;
|
import ru.gravit.launcher.hasher.HashedEntry;
|
||||||
|
@ -10,10 +9,10 @@
|
||||||
import ru.gravit.launcher.request.ResultInterface;
|
import ru.gravit.launcher.request.ResultInterface;
|
||||||
import ru.gravit.utils.helper.LogHelper;
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
|
||||||
|
@ -27,8 +26,8 @@ public class ClientWebSocketService extends ClientJSONPoint {
|
||||||
private HashMap<String, Class<? extends ResultInterface>> results;
|
private HashMap<String, Class<? extends ResultInterface>> results;
|
||||||
private HashSet<EventHandler> handlers;
|
private HashSet<EventHandler> handlers;
|
||||||
|
|
||||||
public ClientWebSocketService(GsonBuilder gsonBuilder, String address, int i) {
|
public ClientWebSocketService(GsonBuilder gsonBuilder, String address, int i) throws SSLException {
|
||||||
super(createURL(address), Collections.emptyMap(), i);
|
super(createURL(address));
|
||||||
requests = new HashMap<>();
|
requests = new HashMap<>();
|
||||||
results = new HashMap<>();
|
results = new HashMap<>();
|
||||||
handlers = new HashSet<>();
|
handlers = new HashSet<>();
|
||||||
|
@ -51,7 +50,7 @@ private static URI createURL(String address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onMessage(String message) {
|
void onMessage(String message) {
|
||||||
ResultInterface result = gson.fromJson(message, ResultInterface.class);
|
ResultInterface result = gson.fromJson(message, ResultInterface.class);
|
||||||
for (EventHandler handler : handlers) {
|
for (EventHandler handler : handlers) {
|
||||||
handler.process(result);
|
handler.process(result);
|
||||||
|
@ -59,25 +58,19 @@ public void onMessage(String message) {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onError(Exception e) {
|
void onDisconnect() {
|
||||||
LogHelper.error(e);
|
LogHelper.info("WebSocket client disconnect");
|
||||||
|
if(onCloseCallback != null) onCloseCallback.onClose(0,"unsupported param", !isClosed);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpen(ServerHandshake handshakedata) {
|
void onOpen() throws Exception {
|
||||||
//Notify open
|
|
||||||
synchronized (onConnect)
|
synchronized (onConnect)
|
||||||
{
|
{
|
||||||
onConnect.notifyAll();
|
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
|
@FunctionalInterface
|
||||||
public interface OnCloseCallback
|
public interface OnCloseCallback
|
||||||
{
|
{
|
||||||
|
@ -136,7 +129,7 @@ public void registerHandler(EventHandler eventHandler) {
|
||||||
}
|
}
|
||||||
public void waitIfNotConnected()
|
public void waitIfNotConnected()
|
||||||
{
|
{
|
||||||
if(!isOpen() && !isClosed() && !isClosing())
|
/*if(!isOpen() && !isClosed() && !isClosing())
|
||||||
{
|
{
|
||||||
LogHelper.warning("WebSocket not connected. Try wait onConnect object");
|
LogHelper.warning("WebSocket not connected. Try wait onConnect object");
|
||||||
synchronized (onConnect)
|
synchronized (onConnect)
|
||||||
|
@ -147,20 +140,22 @@ public void waitIfNotConnected()
|
||||||
LogHelper.error(e);
|
LogHelper.error(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObject(Object obj) throws IOException {
|
public void sendObject(Object obj) throws IOException {
|
||||||
waitIfNotConnected();
|
waitIfNotConnected();
|
||||||
if(isClosed() && reconnectCallback != null)
|
if(ch == null || !ch.isActive()) reconnectCallback.onReconnect();
|
||||||
reconnectCallback.onReconnect();
|
//if(isClosed() && reconnectCallback != null)
|
||||||
|
// reconnectCallback.onReconnect();
|
||||||
send(gson.toJson(obj, RequestInterface.class));
|
send(gson.toJson(obj, RequestInterface.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void sendObject(Object obj, Type type) throws IOException {
|
public void sendObject(Object obj, Type type) throws IOException {
|
||||||
waitIfNotConnected();
|
waitIfNotConnected();
|
||||||
if(isClosed() && reconnectCallback != null)
|
if(ch == null || !ch.isActive()) reconnectCallback.onReconnect();
|
||||||
reconnectCallback.onReconnect();
|
//if(isClosed() && reconnectCallback != null)
|
||||||
|
// reconnectCallback.onReconnect();
|
||||||
send(gson.toJson(obj, type));
|
send(gson.toJson(obj, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import ru.gravit.utils.helper.JVMHelper;
|
import ru.gravit.utils.helper.JVMHelper;
|
||||||
import ru.gravit.utils.helper.LogHelper;
|
import ru.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
import javax.net.ssl.SSLException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
@ -15,7 +16,7 @@
|
||||||
|
|
||||||
public class StandartClientWebSocketService extends ClientWebSocketService {
|
public class StandartClientWebSocketService extends ClientWebSocketService {
|
||||||
public WaitEventHandler waitEventHandler = new WaitEventHandler();
|
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);
|
super(gsonBuilder, address, i);
|
||||||
}
|
}
|
||||||
public class RequestFuture implements Future<ResultInterface>
|
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) {
|
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.registerResults();
|
||||||
service.registerRequests();
|
service.registerRequests();
|
||||||
service.registerHandler(service.waitEventHandler);
|
service.registerHandler(service.waitEventHandler);
|
||||||
if(!async)
|
if(!async)
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (!service.connectBlocking()) LogHelper.error("Error connecting");
|
service.open();
|
||||||
LogHelper.debug("Connect to %s", address);
|
LogHelper.debug("Connect to %s", address);
|
||||||
} catch (InterruptedException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
service.connect();
|
try {
|
||||||
|
service.open();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
JVMHelper.RUNTIME.addShutdownHook(new Thread(() -> {
|
JVMHelper.RUNTIME.addShutdownHook(new Thread(() -> {
|
||||||
try {
|
try {
|
||||||
if(service.isOpen())
|
//if(service.isOpen())
|
||||||
service.closeBlocking();
|
// service.closeBlocking();
|
||||||
|
service.close();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
LogHelper.error(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
|
* Discord channel: https://discord.gg/aJK6nMN
|
||||||
* [See license](LICENSE)
|
* [See license](LICENSE)
|
||||||
* [See code of conduct](CODE_OF_CONDUCT.md)
|
* [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):
|
* Get it (requires cURL):
|
||||||
```sh
|
```sh
|
||||||
curl -s https://raw.githubusercontent.com/GravitLauncher/Launcher/master/get_it.sh | 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 mainClassName = "ru.gravit.launcher.server.ServerWrapper"
|
||||||
String mainAgentName = "ru.gravit.launcher.server.ServerAgent"
|
String mainAgentName = "ru.gravit.launcher.server.ServerAgent"
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
pack
|
||||||
|
compile.extendsFrom pack
|
||||||
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
maven {
|
maven {
|
||||||
|
@ -12,6 +18,7 @@
|
||||||
targetCompatibility = '1.8'
|
targetCompatibility = '1.8'
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
|
classifier = 'clean'
|
||||||
from { configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } }
|
from { configurations.runtime.collect { it.isDirectory() ? it : zipTree(it) } }
|
||||||
manifest.attributes("Main-Class": mainClassName,
|
manifest.attributes("Main-Class": mainClassName,
|
||||||
"Premain-Class": mainAgentName,
|
"Premain-Class": mainAgentName,
|
||||||
|
@ -21,5 +28,18 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
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.events.request.ProfilesRequestEvent;
|
||||||
import ru.gravit.launcher.profiles.ClientProfile;
|
import ru.gravit.launcher.profiles.ClientProfile;
|
||||||
import ru.gravit.launcher.request.Request;
|
import ru.gravit.launcher.request.Request;
|
||||||
|
import ru.gravit.launcher.request.RequestException;
|
||||||
import ru.gravit.launcher.request.auth.AuthRequest;
|
import ru.gravit.launcher.request.auth.AuthRequest;
|
||||||
import ru.gravit.launcher.request.update.ProfilesRequest;
|
import ru.gravit.launcher.request.update.ProfilesRequest;
|
||||||
import ru.gravit.launcher.server.setup.ServerWrapperSetup;
|
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");
|
LogHelper.debug("WebSocket connect closed. Try reconnect");
|
||||||
try {
|
try {
|
||||||
if (!Request.service.reconnectBlocking()) LogHelper.error("Error connecting");
|
Request.service.open();
|
||||||
LogHelper.debug("Connect to %s", config.websocket.address);
|
LogHelper.debug("Connect to %s", config.websocket.address);
|
||||||
} catch (InterruptedException e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
LogHelper.error(e);
|
||||||
|
throw new RequestException(String.format("Connect error: %s", e.getMessage() != null ? e.getMessage() : "null"));
|
||||||
}
|
}
|
||||||
auth();
|
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("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name);
|
||||||
LogHelper.info("Start Minecraft Server");
|
LogHelper.info("Start Minecraft Server");
|
||||||
LogHelper.debug("Invoke main method %s", mainClass.getName());
|
LogHelper.debug("Invoke main method %s", mainClass.getName());
|
||||||
|
|
|
@ -67,6 +67,7 @@ public void run() throws IOException {
|
||||||
wrapper.config.password = password;
|
wrapper.config.password = password;
|
||||||
wrapper.config.title = title;
|
wrapper.config.title = title;
|
||||||
wrapper.config.stopOnError = false;
|
wrapper.config.stopOnError = false;
|
||||||
|
wrapper.updateLauncherConfig();
|
||||||
|
|
||||||
if (wrapper.auth()) {
|
if (wrapper.auth()) {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -60,7 +60,7 @@ public final class Launcher {
|
||||||
public static final int MAJOR = 5;
|
public static final int MAJOR = 5;
|
||||||
public static final int MINOR = 0;
|
public static final int MINOR = 0;
|
||||||
public static final int PATCH = 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 final Version.Type RELEASE = Version.Type.BETA;
|
||||||
public static GsonManager gsonManager;
|
public static GsonManager gsonManager;
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,8 @@ public enum Version {
|
||||||
MC1122("1.12.2", 340),
|
MC1122("1.12.2", 340),
|
||||||
MC113("1.13", 393),
|
MC113("1.13", 393),
|
||||||
MC1131("1.13.1", 401),
|
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;
|
private static final Map<String, Version> VERSIONS;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
|
|
@ -6,8 +6,6 @@
|
||||||
public class LauncherSSLContext {
|
public class LauncherSSLContext {
|
||||||
public SSLServerSocketFactory ssf;
|
public SSLServerSocketFactory ssf;
|
||||||
public SSLSocketFactory sf;
|
public SSLSocketFactory sf;
|
||||||
@SuppressWarnings("unused")
|
|
||||||
private SSLContext sc;
|
|
||||||
|
|
||||||
public LauncherSSLContext(KeyStore ks, String keypassword) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, KeyManagementException {
|
public LauncherSSLContext(KeyStore ks, String keypassword) throws NoSuchAlgorithmException, KeyStoreException, UnrecoverableKeyException, KeyManagementException {
|
||||||
TrustManager[] trustAllCerts = new TrustManager[]{
|
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.ManagementFactory;
|
||||||
import java.lang.management.OperatingSystemMXBean;
|
import java.lang.management.OperatingSystemMXBean;
|
||||||
import java.lang.management.RuntimeMXBean;
|
import java.lang.management.RuntimeMXBean;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -52,8 +50,6 @@ public static OS byName(String name) {
|
||||||
public static final int OS_BITS = getCorrectOSArch();
|
public static final int OS_BITS = getCorrectOSArch();
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static final int JVM_BITS = Integer.parseInt(System.getProperty("sun.arch.data.model"));
|
public static final int JVM_BITS = Integer.parseInt(System.getProperty("sun.arch.data.model"));
|
||||||
@LauncherAPI
|
|
||||||
public static final int RAM = getRAMAmount();
|
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static final SecurityManager SECURITY_MANAGER = System.getSecurityManager();
|
public static final SecurityManager SECURITY_MANAGER = System.getSecurityManager();
|
||||||
|
@ -137,19 +133,6 @@ public static String getEnvPropertyCaseSensitive(String name) {
|
||||||
return System.getenv().get(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
|
@LauncherAPI
|
||||||
public static boolean isJVMMatchesSystemArch() {
|
public static boolean isJVMMatchesSystemArch() {
|
||||||
return JVM_BITS == OS_BITS;
|
return JVM_BITS == OS_BITS;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import java.util.function.Consumer;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
public final class LogHelper {
|
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<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 static final OutputEnity STD_OUTPUT;
|
||||||
|
|
||||||
private LogHelper() {
|
private LogHelper() {
|
||||||
|
@ -60,6 +62,11 @@ public static void addOutput(OutputEnity output) {
|
||||||
OUTPUTS.add(Objects.requireNonNull(output, "output"));
|
OUTPUTS.add(Objects.requireNonNull(output, "output"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@LauncherAPI
|
||||||
|
public static void addExcCallback(Consumer<Throwable> output) {
|
||||||
|
EXCEPTIONS_CALLBACKS.add(Objects.requireNonNull(output, "output"));
|
||||||
|
}
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static void addOutput(Output output, OutputTypes type) {
|
public static void addOutput(Output output, OutputTypes type) {
|
||||||
OUTPUTS.add(new OutputEnity(Objects.requireNonNull(output, "output"), type));
|
OUTPUTS.add(new OutputEnity(Objects.requireNonNull(output, "output"), type));
|
||||||
|
@ -105,6 +112,7 @@ public static void dev(String format, Object... args) {
|
||||||
|
|
||||||
@LauncherAPI
|
@LauncherAPI
|
||||||
public static void error(Throwable exc) {
|
public static void error(Throwable exc) {
|
||||||
|
EXCEPTIONS_CALLBACKS.forEach(e -> e.accept(exc));
|
||||||
error(isStacktraceEnabled() ? toString(exc) : exc.toString());
|
error(isStacktraceEnabled() ? toString(exc) : exc.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue