[FEATURE] Update rework

This commit is contained in:
Gravita 2022-08-24 13:40:53 +07:00
parent 9bac9e3bef
commit 230194f2a0
14 changed files with 103 additions and 70 deletions

View file

@ -124,9 +124,8 @@ protected void initProps() {
server.runtime.clientCheckSecret.concat(".").concat(launcherSalt)); server.runtime.clientCheckSecret.concat(".").concat(launcherSalt));
properties.put("runtimeconfig.secureCheckHash", Base64.getEncoder().encodeToString(launcherSecureHash)); properties.put("runtimeconfig.secureCheckHash", Base64.getEncoder().encodeToString(launcherSecureHash));
properties.put("runtimeconfig.secureCheckSalt", launcherSalt); properties.put("runtimeconfig.secureCheckSalt", launcherSalt);
//LogHelper.debug("[checkSecure] %s: %s", launcherSalt, Arrays.toString(launcherSecureHash)); if (server.runtime.unlockSecret == null) server.runtime.unlockSecret = SecurityHelper.randomStringToken();
if (server.runtime.oemUnlockKey == null) server.runtime.oemUnlockKey = SecurityHelper.randomStringToken(); properties.put("runtimeconfig.unlockSecret", server.runtime.unlockSecret);
properties.put("runtimeconfig.oemUnlockKey", server.runtime.oemUnlockKey);
} }

View file

@ -45,7 +45,7 @@ public final class LaunchServerConfig {
public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) { public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
LaunchServerConfig newConfig = new LaunchServerConfig(); LaunchServerConfig newConfig = new LaunchServerConfig();
newConfig.mirrors = new String[]{"https://mirror.gravit.pro/5.2.x/", "https://gravit-launcher-mirror.storage.googleapis.com/"}; newConfig.mirrors = new String[]{"https://mirror.gravit.pro/5.3.x/", "https://gravit-launcher-mirror.storage.googleapis.com/"};
newConfig.launch4j = new LaunchServerConfig.ExeConf(); newConfig.launch4j = new LaunchServerConfig.ExeConf();
newConfig.launch4j.enabled = false; newConfig.launch4j.enabled = false;
newConfig.launch4j.copyright = "© GravitLauncher Team"; newConfig.launch4j.copyright = "© GravitLauncher Team";
@ -168,9 +168,9 @@ public void verify() {
boolean updateMirror = Boolean.getBoolean("launchserver.config.disableUpdateMirror"); boolean updateMirror = Boolean.getBoolean("launchserver.config.disableUpdateMirror");
if(!updateMirror) { if(!updateMirror) {
for(int i=0;i < mirrors.length;++i) { for(int i=0;i < mirrors.length;++i) {
if("https://mirror.gravit.pro/".equals(mirrors[i])) { if("https://mirror.gravit.pro/5.2.x/".equals(mirrors[i])) {
logger.warn("Replace mirror 'https://mirror.gravit.pro/' to 'https://mirror.gravit.pro/5.2.x/'. If you really need to use original url, use '-Dlaunchserver.config.disableUpdateMirror=true'"); logger.warn("Replace mirror 'https://mirror.gravit.pro/5.2.x/' to 'https://mirror.gravit.pro/5.3.x/'. If you really need to use original url, use '-Dlaunchserver.config.disableUpdateMirror=true'");
mirrors[i] = "https://mirror.gravit.pro/5.2.x/"; mirrors[i] = "https://mirror.gravit.pro/5.3.x/";
} }
} }
} }
@ -278,8 +278,6 @@ public static class LauncherConf {
public static class NettyConfig { public static class NettyConfig {
public boolean fileServerEnabled; public boolean fileServerEnabled;
@Deprecated
public boolean sendExceptionEnabled;
public boolean ipForwarding; public boolean ipForwarding;
public boolean disableWebApiInterface; public boolean disableWebApiInterface;
public boolean showHiddenFiles; public boolean showHiddenFiles;

View file

@ -8,7 +8,7 @@ public class LaunchServerRuntimeConfig {
private transient final Logger logger = LogManager.getLogger(); private transient final Logger logger = LogManager.getLogger();
public String passwordEncryptKey; public String passwordEncryptKey;
public String runtimeEncryptKey; public String runtimeEncryptKey;
public String oemUnlockKey; public String unlockSecret;
public String registerApiKey; public String registerApiKey;
public String clientCheckSecret; public String clientCheckSecret;

View file

@ -50,6 +50,7 @@ task javadocJar(type: Jar) {
dependencies { dependencies {
pack project(':LauncherAPI') pack project(':LauncherAPI')
bundle group: 'com.github.oshi', name: 'oshi-core', version: rootProject['verOshiCore'] bundle group: 'com.github.oshi', name: 'oshi-core', version: rootProject['verOshiCore']
bundle "pro.gravit.utils.enfs:enfs:1.0.0-SNAPSHOT"
pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty'] pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty']
} }

View file

@ -84,11 +84,14 @@ public static void checkClass(Class<?> clazz) throws SecurityException {
} }
} }
public static void exitLauncher(int code) { public static void beforeExit(int code) {
try { try {
modulesManager.invokeEvent(new ClientExitPhase(code)); modulesManager.invokeEvent(new ClientExitPhase(code));
} catch (Throwable ignored) { } catch (Throwable ignored) {
} }
}
public static void forceExit(int code) {
try { try {
System.exit(code); System.exit(code);
} catch (Throwable e) //Forge Security Manager? } catch (Throwable e) //Forge Security Manager?
@ -97,6 +100,11 @@ public static void exitLauncher(int code) {
} }
} }
public static void exitLauncher(int code) {
beforeExit(code);
forceExit(code);
}
public static void main(String... args) throws Throwable { public static void main(String... args) throws Throwable {
JVMHelper.checkStackTrace(LauncherEngine.class); JVMHelper.checkStackTrace(LauncherEngine.class);
JVMHelper.verifySystemProperties(Launcher.class, true); JVMHelper.verifySystemProperties(Launcher.class, true);

View file

@ -26,7 +26,7 @@ public class DebugMain {
public static final AtomicBoolean IS_DEBUG = new AtomicBoolean(false); public static final AtomicBoolean IS_DEBUG = new AtomicBoolean(false);
public static String webSocketURL = System.getProperty("launcherdebug.websocket", "ws://localhost:9274/api"); public static String webSocketURL = System.getProperty("launcherdebug.websocket", "ws://localhost:9274/api");
public static String projectName = System.getProperty("launcherdebug.projectname", "Minecraft"); public static String projectName = System.getProperty("launcherdebug.projectname", "Minecraft");
public static String unlockKey = System.getProperty("launcherdebug.unlockkey", "0000"); public static String unlockSecret = System.getProperty("launcherdebug.unlocksecret", "");
public static boolean offlineMode = Boolean.getBoolean("launcherdebug.offlinemode"); public static boolean offlineMode = Boolean.getBoolean("launcherdebug.offlinemode");
public static String[] moduleClasses = System.getProperty("launcherdebug.modules", "").split(","); public static String[] moduleClasses = System.getProperty("launcherdebug.modules", "").split(",");
public static String[] moduleFiles = System.getProperty("launcherdebug.modulefiles", "").split(","); public static String[] moduleFiles = System.getProperty("launcherdebug.modulefiles", "").split(",");
@ -39,7 +39,7 @@ public static void main(String[] args) throws Throwable {
LogHelper.info("Launcher start in DEBUG mode (Only for developers)"); LogHelper.info("Launcher start in DEBUG mode (Only for developers)");
LogHelper.debug("Initialization LauncherConfig"); LogHelper.debug("Initialization LauncherConfig");
LauncherConfig config = new LauncherConfig(webSocketURL, new HashMap<>(), projectName, environment, new DebugLauncherTrustManager(DebugLauncherTrustManager.TrustDebugMode.TRUST_ALL)); LauncherConfig config = new LauncherConfig(webSocketURL, new HashMap<>(), projectName, environment, new DebugLauncherTrustManager(DebugLauncherTrustManager.TrustDebugMode.TRUST_ALL));
config.oemUnlockKey = unlockKey; config.unlockSecret = unlockSecret;
Launcher.setConfig(config); Launcher.setConfig(config);
Launcher.applyLauncherEnv(environment); Launcher.applyLauncherEnv(environment);
LauncherEngine.modulesManager = new ClientModuleManager(); LauncherEngine.modulesManager = new ClientModuleManager();

View file

@ -49,7 +49,7 @@ public static void registerCommands() {
} }
public static boolean checkUnlockKey(String key) { public static boolean checkUnlockKey(String key) {
return key.equals(Launcher.getConfig().oemUnlockKey); return key.equals(Launcher.getConfig().unlockSecret);
} }
public static boolean unlock() { public static boolean unlock() {

View file

@ -0,0 +1,65 @@
package pro.gravit.launcher.utils;
import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.LauncherEngine;
import pro.gravit.launcher.events.request.LauncherRequestEvent;
import pro.gravit.launcher.request.update.LauncherRequest;
import pro.gravit.utils.helper.IOHelper;
import pro.gravit.utils.helper.LogHelper;
import pro.gravit.utils.helper.SecurityHelper;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardOpenOption;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class LauncherUpdater {
public static void nothing() {
}
private static Path getLauncherPath() {
Path pathToCore = IOHelper.getCodeSource(IOHelper.class);
Path pathToApi = IOHelper.getCodeSource(LauncherRequest.class);
Path pathToSelf = IOHelper.getCodeSource(LauncherUpdater.class);
if(pathToCore.equals(pathToApi) && pathToCore.equals(pathToSelf)) {
return pathToCore;
} else {
throw new SecurityException("Found split-jar launcher");
}
}
public static Path prepareUpdate(URL url) throws Exception {
Path pathToLauncher = getLauncherPath();
Path tempFile = Files.createTempFile("launcher-update-", ".jar");
URLConnection connection = url.openConnection();
try (InputStream in = connection.getInputStream()) {
IOHelper.transfer(in, tempFile);
}
if (Arrays.equals(SecurityHelper.digest(SecurityHelper.DigestAlgorithm.MD5, tempFile),
SecurityHelper.digest(SecurityHelper.DigestAlgorithm.MD5, pathToLauncher)))
throw new IOException("Invalid update (launcher needs update, but link has old launcher), check LaunchServer config...");
return tempFile;
}
public static void restart() {
List<String> args = new ArrayList<>(8);
args.add(IOHelper.resolveJavaBin(null).toString());
args.add("-jar");
args.add(IOHelper.getCodeSource(LauncherUpdater.class).toString());
ProcessBuilder builder = new ProcessBuilder(args.toArray(new String[0]));
builder.inheritIO();
try {
builder.start();
} catch (IOException e) {
LogHelper.error(e);
}
LauncherEngine.forceExit(0);
}
}

View file

@ -46,8 +46,8 @@ public final class LauncherConfig extends StreamObject {
public final String address; public final String address;
@LauncherInject("runtimeconfig.secretKeyClient") @LauncherInject("runtimeconfig.secretKeyClient")
public String secretKeyClient; public String secretKeyClient;
@LauncherInject("runtimeconfig.oemUnlockKey") @LauncherInject("runtimeconfig.unlockSecret")
public String oemUnlockKey; public String unlockSecret;
@LauncherInject("launchercore.env") @LauncherInject("launchercore.env")
public LauncherEnvironment environment; public LauncherEnvironment environment;
@ -63,7 +63,6 @@ public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException
projectName = null; projectName = null;
clientPort = -1; clientPort = -1;
secretKeyClient = null; secretKeyClient = null;
oemUnlockKey = null;
try { try {
trustManager = new LauncherTrustManager(secureConfigCertificates); trustManager = new LauncherTrustManager(secureConfigCertificates);
} catch (CertificateException e) { } catch (CertificateException e) {

View file

@ -23,7 +23,6 @@
public final class LauncherRequest extends Request<LauncherRequestEvent> implements WebSocketRequest { public final class LauncherRequest extends Request<LauncherRequestEvent> implements WebSocketRequest {
public static final Path BINARY_PATH = IOHelper.getCodeSource(Launcher.class); public static final Path BINARY_PATH = IOHelper.getCodeSource(Launcher.class);
public static final Path C_BINARY_PATH = BINARY_PATH.getParent().resolve(IOHelper.getFileName(BINARY_PATH) + ".tmp");
public static final boolean EXE_BINARY = IOHelper.hasExtension(BINARY_PATH, "exe"); public static final boolean EXE_BINARY = IOHelper.hasExtension(BINARY_PATH, "exe");
@LauncherNetworkAPI @LauncherNetworkAPI
public final String secureHash; public final String secureHash;
@ -46,53 +45,9 @@ public LauncherRequest() {
secureSalt = Launcher.getConfig().secureCheckSalt; secureSalt = Launcher.getConfig().secureCheckSalt;
} }
public static void update(LauncherRequestEvent result) throws IOException {
List<String> args = new ArrayList<>(8);
args.add(IOHelper.resolveJavaBin(null).toString());
if (LogHelper.isDebugEnabled())
args.add(JVMHelper.jvmProperty(LogHelper.DEBUG_PROPERTY, Boolean.toString(LogHelper.isDebugEnabled())));
args.add("-jar");
args.add(BINARY_PATH.toString());
ProcessBuilder builder = new ProcessBuilder(args.toArray(new String[0]));
builder.inheritIO();
// Rewrite and start new instance
if (result.binary != null)
IOHelper.write(BINARY_PATH, result.binary);
else {
/*URLConnection connection = IOHelper.newConnection(new URL(result.url));
connection.setDoOutput(true);
connection.connect();
try (OutputStream stream = connection.getOutputStream()) {
IOHelper.transfer(BINARY_PATH, stream);
}*/
try {
Files.deleteIfExists(C_BINARY_PATH);
URL url = new URL(result.url);
URLConnection connection = url.openConnection();
try (InputStream in = connection.getInputStream()) {
IOHelper.transfer(in, C_BINARY_PATH);
}
try (InputStream in = IOHelper.newInput(C_BINARY_PATH)) {
IOHelper.transfer(in, BINARY_PATH);
}
Files.deleteIfExists(C_BINARY_PATH);
} catch (Throwable e) {
LogHelper.error(e);
}
}
builder.start();
// Kill current instance
JVMHelper.RUNTIME.exit(255);
throw new AssertionError("Why Launcher wasn't restarted?!");
}
@Override @Override
public LauncherRequestEvent requestDo(RequestService service) throws Exception { public LauncherRequestEvent requestDo(RequestService service) throws Exception {
LauncherRequestEvent result = super.request(service); return super.request(service);
if (result.needUpdate) update(result);
return result;
} }
@Override @Override

Binary file not shown.

View file

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.1-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

6
gradlew vendored
View file

@ -205,6 +205,12 @@ set -- \
org.gradle.wrapper.GradleWrapperMain \ org.gradle.wrapper.GradleWrapperMain \
"$@" "$@"
# Stop when "xargs" is not available.
if ! command -v xargs >/dev/null 2>&1
then
die "xargs is not available"
fi
# Use "xargs" to parse quoted args. # Use "xargs" to parse quoted args.
# #
# With -n1 it outputs one arg per line, with the quotes and backslashes removed. # With -n1 it outputs one arg per line, with the quotes and backslashes removed.

10
gradlew.bat vendored
View file

@ -40,7 +40,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto execute if %ERRORLEVEL% equ 0 goto execute
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
@ -75,13 +75,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd if %ERRORLEVEL% equ 0 goto mainEnd
:fail :fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code! rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 set EXIT_CODE=%ERRORLEVEL%
exit /b 1 if %EXIT_CODE% equ 0 set EXIT_CODE=1
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
exit /b %EXIT_CODE%
:mainEnd :mainEnd
if "%OS%"=="Windows_NT" endlocal if "%OS%"=="Windows_NT" endlocal