mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-11-15 11:39:11 +03:00
Merge branch 'dev' into feature/design
This commit is contained in:
commit
405caef0f4
123 changed files with 1018 additions and 920 deletions
37
.gitlab-ci.yml
Normal file
37
.gitlab-ci.yml
Normal file
|
@ -0,0 +1,37 @@
|
|||
image: java:8-jdk
|
||||
|
||||
stages:
|
||||
- build
|
||||
- test
|
||||
- deploy
|
||||
|
||||
before_script:
|
||||
# - echo `pwd` # debug
|
||||
# - echo "$CI_BUILD_NAME, $CI_BUILD_REF_NAME $CI_BUILD_STAGE" # debug
|
||||
- export GRADLE_USER_HOME=`pwd`/.gradle
|
||||
|
||||
cache:
|
||||
paths:
|
||||
- .gradle/wrapper
|
||||
- .gradle/caches
|
||||
|
||||
build:
|
||||
stage: build
|
||||
script:
|
||||
- sed -i 's/git@github.com:/https:\/\/github.com\//' .gitmodules
|
||||
- git submodule sync
|
||||
- git submodule update --init --recursive
|
||||
- ./gradlew assemble
|
||||
artifacts:
|
||||
paths:
|
||||
- LaunchServer/build/libs/*
|
||||
- ServerWrapper/build/libs/*.jar
|
||||
expire_in: 1 week
|
||||
|
||||
test:
|
||||
stage: test
|
||||
script:
|
||||
- ./gradlew check
|
||||
|
||||
after_script:
|
||||
- echo "End CI"
|
|
@ -16,4 +16,4 @@ cache:
|
|||
- $HOME/.gradle/caches/
|
||||
- $HOME/.gradle/wrapper/
|
||||
script:
|
||||
- ./gradlew build
|
||||
- ./gradlew build
|
||||
|
|
|
@ -44,13 +44,15 @@
|
|||
pack project(':libLauncher')
|
||||
pack project(':LauncherAPI')
|
||||
bundle project(':Radon')
|
||||
bundle 'mysql:mysql-connector-java:8.0.13'
|
||||
bundle 'jline:jline:2.14.6'
|
||||
bundle 'net.sf.proguard:proguard-base:6.0.3'
|
||||
bundle 'org.fusesource.jansi:jansi:1.17.1'
|
||||
bundle 'mysql:mysql-connector-java:8.0.16'
|
||||
bundle 'org.jline:jline:3.11.0'
|
||||
bundle 'org.jline:jline-reader:3.11.0'
|
||||
bundle 'org.jline:jline-terminal:3.11.0'
|
||||
bundle 'net.sf.proguard:proguard-base:6.1.0'
|
||||
bundle 'org.fusesource.jansi:jansi:1.18'
|
||||
bundle 'commons-io:commons-io:2.6'
|
||||
bundle 'commons-codec:commons-codec:1.11'
|
||||
bundle 'org.javassist:javassist:3.24.1-GA'
|
||||
bundle 'commons-codec:commons-codec:1.12'
|
||||
bundle 'org.javassist:javassist:3.25.0-GA'
|
||||
bundle 'io.netty:netty-all:4.1.36.Final'
|
||||
|
||||
bundle 'org.slf4j:slf4j-simple:1.7.25'
|
||||
|
@ -79,8 +81,8 @@ bundle project(':Radon')
|
|||
}
|
||||
|
||||
compileOnlyA 'com.google.guava:guava:26.0-jre'
|
||||
compileOnlyA 'log4j:log4j:1.2.17' // Do not update (laggy dep).
|
||||
compileOnlyA 'org.apache.logging.log4j:log4j-core:2.11.2'
|
||||
compileOnlyA 'log4j:log4j:1.2.17' // Do not update (laggy dep).
|
||||
compileOnlyA 'org.apache.logging.log4j:log4j-core:2.11.2'
|
||||
}
|
||||
|
||||
task hikari(type: Copy) {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.launcher.LauncherConfig;
|
||||
import ru.gravit.launcher.NeedGarbageCollection;
|
||||
import ru.gravit.launcher.config.JsonConfigurable;
|
||||
import ru.gravit.launcher.hasher.HashedDir;
|
||||
import ru.gravit.launcher.managers.ConfigManager;
|
||||
import ru.gravit.launcher.managers.GarbageManager;
|
||||
|
@ -38,7 +39,6 @@
|
|||
import ru.gravit.utils.command.CommandHandler;
|
||||
import ru.gravit.utils.command.JLineCommandHandler;
|
||||
import ru.gravit.utils.command.StdCommandHandler;
|
||||
import ru.gravit.launcher.config.JsonConfigurable;
|
||||
import ru.gravit.utils.helper.*;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -81,7 +81,7 @@ public static final class Config {
|
|||
public String[] mirrors;
|
||||
|
||||
public String binaryName;
|
||||
|
||||
|
||||
public boolean copyBinaries = true;
|
||||
|
||||
public LauncherConfig.LauncherEnvironment env;
|
||||
|
@ -200,8 +200,8 @@ public void verify() {
|
|||
throw new NullPointerException("Netty must not be null");
|
||||
}
|
||||
}
|
||||
public void init()
|
||||
{
|
||||
|
||||
public void init() {
|
||||
Launcher.applyLauncherEnv(env);
|
||||
for (AuthProviderPair provider : auth) {
|
||||
provider.init();
|
||||
|
@ -212,8 +212,7 @@ public void init()
|
|||
protectHandler.checkLaunchServerLicense();
|
||||
}
|
||||
LaunchServer.server.registerObject("permissionsHandler", permissionsHandler);
|
||||
for (int i = 0; i < auth.length; ++i) {
|
||||
AuthProviderPair pair = auth[i];
|
||||
for (AuthProviderPair pair : auth) {
|
||||
LaunchServer.server.registerObject("auth.".concat(pair.name).concat(".provider"), pair.provider);
|
||||
LaunchServer.server.registerObject("auth.".concat(pair.name).concat(".handler"), pair.handler);
|
||||
LaunchServer.server.registerObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider);
|
||||
|
@ -225,14 +224,12 @@ public void init()
|
|||
public void close() {
|
||||
try {
|
||||
LaunchServer.server.unregisterObject("permissionsHandler", permissionsHandler);
|
||||
for (int i = 0; i < auth.length; ++i) {
|
||||
AuthProviderPair pair = auth[i];
|
||||
for (AuthProviderPair pair : auth) {
|
||||
LaunchServer.server.unregisterObject("auth.".concat(pair.name).concat(".provider"), pair.provider);
|
||||
LaunchServer.server.unregisterObject("auth.".concat(pair.name).concat(".handler"), pair.handler);
|
||||
LaunchServer.server.unregisterObject("auth.".concat(pair.name).concat(".texture"), pair.textureProvider);
|
||||
}
|
||||
} catch (Exception e)
|
||||
{
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
try {
|
||||
|
@ -266,10 +263,15 @@ public static class ExeConf {
|
|||
public String txtFileVersion;
|
||||
public String txtProductVersion;
|
||||
}
|
||||
|
||||
public class LauncherConf
|
||||
public static class NettyUpdatesBind
|
||||
{
|
||||
public String url;
|
||||
public boolean zip;
|
||||
}
|
||||
|
||||
public class LauncherConf {
|
||||
public String guardType;
|
||||
public boolean attachLibraryBeforeProGuard;
|
||||
}
|
||||
|
||||
public class NettyConfig {
|
||||
|
@ -280,19 +282,19 @@ public class NettyConfig {
|
|||
public String downloadURL;
|
||||
public String launcherEXEURL;
|
||||
public String address;
|
||||
public Map<String, String> bindings = new HashMap<>();
|
||||
public Map<String, NettyUpdatesBind> bindings = new HashMap<>();
|
||||
public NettyPerformanceConfig performance;
|
||||
public NettyBindAddress[] binds;
|
||||
public LogLevel logLevel = LogLevel.DEBUG;
|
||||
public NettyProxyConfig proxy = new NettyProxyConfig();
|
||||
}
|
||||
public class NettyPerformanceConfig
|
||||
{
|
||||
|
||||
public class NettyPerformanceConfig {
|
||||
public int bossThread;
|
||||
public int workerThread;
|
||||
}
|
||||
public class NettyProxyConfig
|
||||
{
|
||||
|
||||
public class NettyProxyConfig {
|
||||
public boolean enabled;
|
||||
public String address = "ws://localhost:9275/api";
|
||||
public String login = "login";
|
||||
|
@ -300,8 +302,8 @@ public class NettyProxyConfig
|
|||
public String auth_id = "std";
|
||||
public ArrayList<String> requests = new ArrayList<>();
|
||||
}
|
||||
public class NettyBindAddress
|
||||
{
|
||||
|
||||
public class NettyBindAddress {
|
||||
public String address;
|
||||
public int port;
|
||||
|
||||
|
@ -348,8 +350,8 @@ public static void main(String... args) throws Throwable {
|
|||
LogHelper.printVersion("LaunchServer");
|
||||
LogHelper.printLicense("LaunchServer");
|
||||
if (!StarterAgent.isAgentStarted()) {
|
||||
LogHelper.error("StarterAgent is not started!");
|
||||
LogHelper.error("Your should add to JVM options this option: `-javaagent:LaunchServer.jar`");
|
||||
LogHelper.error("StarterAgent is not started!");
|
||||
LogHelper.error("Your should add to JVM options this option: `-javaagent:LaunchServer.jar`");
|
||||
}
|
||||
|
||||
// Start LaunchServer
|
||||
|
@ -373,7 +375,7 @@ public static void main(String... args) throws Throwable {
|
|||
|
||||
public final Path dir;
|
||||
|
||||
public final boolean testEnv;
|
||||
public final boolean testEnv;
|
||||
|
||||
public final Path launcherLibraries;
|
||||
|
||||
|
@ -480,16 +482,16 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
|
|||
if (testEnv)
|
||||
localCommandHandler = new StdCommandHandler(false);
|
||||
else
|
||||
try {
|
||||
Class.forName("jline.Terminal");
|
||||
try {
|
||||
Class.forName("org.jline.terminal.Terminal");
|
||||
|
||||
// JLine2 available
|
||||
localCommandHandler = new JLineCommandHandler();
|
||||
LogHelper.info("JLine2 terminal enabled");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
localCommandHandler = new StdCommandHandler(true);
|
||||
LogHelper.warning("JLine2 isn't in classpath, using std");
|
||||
}
|
||||
// JLine2 available
|
||||
localCommandHandler = new JLineCommandHandler();
|
||||
LogHelper.info("JLine2 terminal enabled");
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
localCommandHandler = new StdCommandHandler(true);
|
||||
LogHelper.warning("JLine2 isn't in classpath, using std");
|
||||
}
|
||||
ru.gravit.launchserver.command.handler.CommandHandler.registerCommands(localCommandHandler);
|
||||
commandHandler = localCommandHandler;
|
||||
|
||||
|
@ -532,14 +534,11 @@ public LaunchServer(Path dir, boolean testEnv, String[] args) throws IOException
|
|||
try (BufferedReader reader = IOHelper.newReader(configFile)) {
|
||||
config = Launcher.gsonManager.gson.fromJson(reader, Config.class);
|
||||
}
|
||||
if(!Files.exists(runtimeConfigFile))
|
||||
{
|
||||
if (!Files.exists(runtimeConfigFile)) {
|
||||
LogHelper.info("Reset LaunchServer runtime config file");
|
||||
runtime = new LaunchServerRuntimeConfig();
|
||||
runtime.reset();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
LogHelper.info("Reading LaunchServer runtime config file");
|
||||
try (BufferedReader reader = IOHelper.newReader(runtimeConfigFile)) {
|
||||
runtime = Launcher.gsonManager.gson.fromJson(reader, LaunchServerRuntimeConfig.class);
|
||||
|
@ -644,14 +643,14 @@ public static void initGson() {
|
|||
}
|
||||
|
||||
private LauncherBinary binary() {
|
||||
if (launcherEXEBinaryClass != null) {
|
||||
try {
|
||||
return launcherEXEBinaryClass.getConstructor(LaunchServer.class).newInstance(this);
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
if (launcherEXEBinaryClass != null) {
|
||||
try {
|
||||
return launcherEXEBinaryClass.getConstructor(LaunchServer.class).newInstance(this);
|
||||
} catch (InstantiationException | IllegalAccessException | IllegalArgumentException
|
||||
| InvocationTargetException | NoSuchMethodException | SecurityException e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
Class.forName("net.sf.launch4j.Builder");
|
||||
if (config.launch4j.enabled) return new EXEL4JLauncherBinary(this);
|
||||
|
@ -674,10 +673,8 @@ public void close() {
|
|||
config.close();
|
||||
modulesManager.close();
|
||||
LogHelper.info("Save LaunchServer runtime config");
|
||||
try(Writer writer = IOHelper.newWriter(runtimeConfigFile))
|
||||
{
|
||||
if(Launcher.gsonManager.configGson != null)
|
||||
{
|
||||
try (Writer writer = IOHelper.newWriter(runtimeConfigFile)) {
|
||||
if (Launcher.gsonManager.configGson != null) {
|
||||
Launcher.gsonManager.configGson.toJson(runtime, writer);
|
||||
} else {
|
||||
LogHelper.error("Error writing LaunchServer runtime config file. Gson is null");
|
||||
|
@ -726,7 +723,7 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
|||
|
||||
newConfig.netty = new NettyConfig();
|
||||
newConfig.netty.fileServerEnabled = true;
|
||||
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.bossThread = 2;
|
||||
newConfig.netty.performance.workerThread = 8;
|
||||
|
@ -754,25 +751,23 @@ private void generateConfigIfNotExists(boolean testEnv) throws IOException {
|
|||
// Set server address
|
||||
String address;
|
||||
if (testEnv) {
|
||||
address = "localhost";
|
||||
newConfig.setProjectName("test");
|
||||
address = "localhost";
|
||||
newConfig.setProjectName("test");
|
||||
} else {
|
||||
System.out.println("LaunchServer address(default: localhost): ");
|
||||
address = commandHandler.readLine();
|
||||
System.out.println("LaunchServer projectName: ");
|
||||
newConfig.setProjectName(commandHandler.readLine());
|
||||
System.out.println("LaunchServer address(default: localhost): ");
|
||||
address = commandHandler.readLine();
|
||||
System.out.println("LaunchServer projectName: ");
|
||||
newConfig.setProjectName(commandHandler.readLine());
|
||||
}
|
||||
if(address == null || address.isEmpty())
|
||||
{
|
||||
if (address == null || address.isEmpty()) {
|
||||
LogHelper.error("Address null. Using localhost");
|
||||
address = "localhost";
|
||||
}
|
||||
if(newConfig.projectName == null || newConfig.projectName.isEmpty())
|
||||
{
|
||||
if (newConfig.projectName == null || newConfig.projectName.isEmpty()) {
|
||||
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%/";
|
||||
|
@ -822,8 +817,8 @@ public void run() {
|
|||
|
||||
// Add shutdown hook, then start LaunchServer
|
||||
if (!this.testEnv) {
|
||||
JVMHelper.RUNTIME.addShutdownHook(CommonHelper.newThread(null, false, this::close));
|
||||
CommonHelper.newThread("Command Thread", true, commandHandler).start();
|
||||
JVMHelper.RUNTIME.addShutdownHook(CommonHelper.newThread(null, false, this::close));
|
||||
CommonHelper.newThread("Command Thread", true, commandHandler).start();
|
||||
}
|
||||
rebindServerSocket();
|
||||
if (config.netty != null)
|
||||
|
@ -869,7 +864,8 @@ public void syncUpdatesDir(Collection<String> dirs) throws IOException {
|
|||
// Resolve name and verify is dir
|
||||
String name = IOHelper.getFileName(updateDir);
|
||||
if (!IOHelper.isDir(updateDir)) {
|
||||
if (!IOHelper.isFile(updateDir) && Arrays.asList(".jar", ".exe", ".hash").stream().noneMatch(e -> updateDir.toString().endsWith(e))) 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;
|
||||
}
|
||||
|
||||
|
@ -920,6 +916,7 @@ public void registerObject(String name, Object object) {
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
public void unregisterObject(String name, Object object) {
|
||||
if (object instanceof Reloadable) {
|
||||
reloadManager.unregisterReloadable(name);
|
||||
|
|
|
@ -15,31 +15,34 @@
|
|||
public final class StarterAgent {
|
||||
|
||||
private static final class StarterVisitor extends SimpleFileVisitor<Path> {
|
||||
private static final Set<PosixFilePermission> DPERMS;
|
||||
static {
|
||||
Set<PosixFilePermission> perms = new HashSet<>(Arrays.asList(PosixFilePermission.values()));
|
||||
perms.remove(PosixFilePermission.OTHERS_WRITE);
|
||||
perms.remove(PosixFilePermission.GROUP_WRITE);
|
||||
DPERMS = Collections.unmodifiableSet(perms);
|
||||
}
|
||||
private static final Set<PosixFilePermission> DPERMS;
|
||||
|
||||
static {
|
||||
Set<PosixFilePermission> perms = new HashSet<>(Arrays.asList(PosixFilePermission.values()));
|
||||
perms.remove(PosixFilePermission.OTHERS_WRITE);
|
||||
perms.remove(PosixFilePermission.GROUP_WRITE);
|
||||
DPERMS = Collections.unmodifiableSet(perms);
|
||||
}
|
||||
|
||||
private final Path filef;
|
||||
private final boolean fixLib;
|
||||
private final boolean fixLib;
|
||||
|
||||
private StarterVisitor() {
|
||||
private StarterVisitor() {
|
||||
this.filef = StarterAgent.libraries.resolve(".libraries_chmoded");
|
||||
this.fixLib = !Files.exists(filef) && !Boolean.getBoolean("launcher.noLibrariesPosixPermsFix");
|
||||
if (fixLib) {
|
||||
try {
|
||||
Files.deleteIfExists(filef);
|
||||
Files.createFile(filef);
|
||||
} catch (Throwable t) { }
|
||||
try {
|
||||
Files.deleteIfExists(filef);
|
||||
Files.createFile(filef);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
|
||||
if (fixLib && Files.getFileAttributeView(file, PosixFileAttributeView.class) != null) Files.setPosixFilePermissions(file, DPERMS);
|
||||
if (fixLib && Files.getFileAttributeView(file, PosixFileAttributeView.class) != null)
|
||||
Files.setPosixFilePermissions(file, DPERMS);
|
||||
if (file.toFile().getName().endsWith(".jar"))
|
||||
inst.appendToSystemClassLoaderSearch(new JarFile(file.toFile()));
|
||||
return super.visitFile(file, attrs);
|
||||
|
|
|
@ -11,24 +11,24 @@ public class JsonAuthHandler extends CachedAuthHandler {
|
|||
public URL getUrl;
|
||||
public URL updateAuthUrl;
|
||||
public URL updateServerIdUrl;
|
||||
public class EntryRequestByUsername
|
||||
{
|
||||
|
||||
public class EntryRequestByUsername {
|
||||
public String username;
|
||||
|
||||
public EntryRequestByUsername(String username) {
|
||||
this.username = username;
|
||||
}
|
||||
}
|
||||
public class EntryRequestByUUID
|
||||
{
|
||||
|
||||
public class EntryRequestByUUID {
|
||||
public UUID uuid;
|
||||
|
||||
public EntryRequestByUUID(UUID uuid) {
|
||||
this.uuid = uuid;
|
||||
}
|
||||
}
|
||||
public class UpdateAuthRequest
|
||||
{
|
||||
|
||||
public class UpdateAuthRequest {
|
||||
public UUID uuid;
|
||||
public String username;
|
||||
public String accessToken;
|
||||
|
@ -39,8 +39,8 @@ public UpdateAuthRequest(UUID uuid, String username, String accessToken) {
|
|||
this.accessToken = accessToken;
|
||||
}
|
||||
}
|
||||
public class UpdateServerIDRequest
|
||||
{
|
||||
|
||||
public class UpdateServerIDRequest {
|
||||
public UUID uuid;
|
||||
public String serverID;
|
||||
|
||||
|
@ -49,10 +49,11 @@ public UpdateServerIDRequest(UUID uuid, String serverID) {
|
|||
this.serverID = serverID;
|
||||
}
|
||||
}
|
||||
public class SuccessResponse
|
||||
{
|
||||
|
||||
public class SuccessResponse {
|
||||
public boolean success;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Entry fetchEntry(String username) throws IOException {
|
||||
return Launcher.gsonManager.configGson.fromJson(HTTPRequest.jsonRequest(Launcher.gsonManager.configGson.toJsonTree(new EntryRequestByUsername(username)), getUrl), Entry.class);
|
||||
|
|
|
@ -38,10 +38,10 @@ protected Entry fetchEntry(UUID uuid) throws IOException {
|
|||
String accessToken = parts[1];
|
||||
String serverID = parts[2];
|
||||
if (LogHelper.isDebugEnabled()) {
|
||||
LogHelper.debug("[AuthHandler] Got username: " + username);
|
||||
LogHelper.debug("[AuthHandler] Got accessToken: " + accessToken);
|
||||
LogHelper.debug("[AuthHandler] Got serverID: " + serverID);
|
||||
LogHelper.debug("[AuthHandler] Got UUID: " + uuid);
|
||||
LogHelper.debug("[AuthHandler] Got username: " + username);
|
||||
LogHelper.debug("[AuthHandler] Got accessToken: " + accessToken);
|
||||
LogHelper.debug("[AuthHandler] Got serverID: " + serverID);
|
||||
LogHelper.debug("[AuthHandler] Got UUID: " + uuid);
|
||||
}
|
||||
return new Entry(uuid, username, accessToken, serverID);
|
||||
}
|
||||
|
@ -54,31 +54,31 @@ protected Entry fetchEntry(String username) throws IOException {
|
|||
String accessToken = parts[1];
|
||||
String serverID = parts[2];
|
||||
if (LogHelper.isDebugEnabled()) {
|
||||
LogHelper.debug("[AuthHandler] Got username: " + username);
|
||||
LogHelper.debug("[AuthHandler] Got accessToken: " + accessToken);
|
||||
LogHelper.debug("[AuthHandler] Got serverID: " + serverID);
|
||||
LogHelper.debug("[AuthHandler] Got UUID: " + uuid);
|
||||
LogHelper.debug("[AuthHandler] Got username: " + username);
|
||||
LogHelper.debug("[AuthHandler] Got accessToken: " + accessToken);
|
||||
LogHelper.debug("[AuthHandler] Got serverID: " + serverID);
|
||||
LogHelper.debug("[AuthHandler] Got UUID: " + uuid);
|
||||
}
|
||||
return new Entry(uuid, username, accessToken, serverID);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateAuth(UUID uuid, String username, String accessToken) throws IOException {
|
||||
String response = IOHelper.request(new URL(CommonHelper.replace(updateAuth, "user", IOHelper.urlEncode(username), "uuid", IOHelper.urlEncode(uuid.toString()), "token", IOHelper.urlEncode(accessToken))));
|
||||
if (LogHelper.isDebugEnabled()) {
|
||||
LogHelper.debug("[AuthHandler] Set accessToken: " + accessToken);
|
||||
LogHelper.debug("[AuthHandler] Set UUID: " + uuid);
|
||||
LogHelper.debug("[AuthHandler] For this username: " + username);
|
||||
String response = IOHelper.request(new URL(CommonHelper.replace(updateAuth, "user", IOHelper.urlEncode(username), "uuid", IOHelper.urlEncode(uuid.toString()), "token", IOHelper.urlEncode(accessToken))));
|
||||
if (LogHelper.isDebugEnabled()) {
|
||||
LogHelper.debug("[AuthHandler] Set accessToken: " + accessToken);
|
||||
LogHelper.debug("[AuthHandler] Set UUID: " + uuid);
|
||||
LogHelper.debug("[AuthHandler] For this username: " + username);
|
||||
}
|
||||
return goodResponse.equals(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean updateServerID(UUID uuid, String serverID) throws IOException {
|
||||
String response = IOHelper.request(new URL(CommonHelper.replace(updateAuth, "serverid", IOHelper.urlEncode(serverID), "uuid", IOHelper.urlEncode(uuid.toString()))));
|
||||
if (LogHelper.isDebugEnabled()) {
|
||||
LogHelper.debug("[AuthHandler] Set serverID: " + serverID);
|
||||
LogHelper.debug("[AuthHandler] For this UUID: " + uuid);
|
||||
String response = IOHelper.request(new URL(CommonHelper.replace(updateAuth, "serverid", IOHelper.urlEncode(serverID), "uuid", IOHelper.urlEncode(uuid.toString()))));
|
||||
if (LogHelper.isDebugEnabled()) {
|
||||
LogHelper.debug("[AuthHandler] Set serverID: " + serverID);
|
||||
LogHelper.debug("[AuthHandler] For this UUID: " + uuid);
|
||||
}
|
||||
return goodResponse.equals(response);
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@ public abstract class ProtectHandler {
|
|||
private static boolean registredHandl = false;
|
||||
|
||||
|
||||
|
||||
public static void registerHandlers() {
|
||||
if (!registredHandl) {
|
||||
providers.register("none", NoProtectHandler.class);
|
||||
|
@ -19,7 +18,9 @@ public static void registerHandlers() {
|
|||
public abstract String generateSecureToken(AuthResponse.AuthContext context); //Генерация токена для передачи его в LauncherGuardInterface
|
||||
|
||||
public abstract String generateClientSecureToken();
|
||||
|
||||
public abstract boolean verifyClientSecureToken(String token, String secureKey);
|
||||
|
||||
public abstract boolean allowGetAccessToken(AuthResponse.AuthContext context);
|
||||
|
||||
public abstract void checkLaunchServerLicense(); //Выдает SecurityException при ошибке проверки лицензии
|
||||
|
|
|
@ -29,7 +29,6 @@ public static void registerProviders() {
|
|||
public abstract AuthProviderResult auth(String login, String password, String ip) throws Exception;
|
||||
|
||||
public void preAuth(String login, String password, String customText, String ip) {
|
||||
return;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -42,10 +42,11 @@ public JARLauncherBinary(LaunchServer server) throws IOException {
|
|||
public void init() {
|
||||
tasks.add(new PrepareBuildTask(server));
|
||||
tasks.add(new MainBuildTask(server));
|
||||
if(server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
|
||||
tasks.add(new ProGuardBuildTask(server));
|
||||
tasks.add(new AdditionalFixesApplyTask(server));
|
||||
tasks.add(new RadonBuildTask(server));
|
||||
tasks.add(new AttachJarsTask(server));
|
||||
if(!server.config.launcher.attachLibraryBeforeProGuard) tasks.add(new AttachJarsTask(server));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -45,8 +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);
|
||||
|
||||
public static Path resolve(LaunchServer server, String ext) {
|
||||
return server.config.copyBinaries ? server.updatesDir.resolve(server.config.binaryName + ext) : server.dir.resolve(server.config.binaryName + ext);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,28 +35,28 @@ public String getName() {
|
|||
public Path process(Path inputFile) throws IOException {
|
||||
Path out = server.launcherBinary.nextPath("post-fixed");
|
||||
try (ZipOutputStream output = new ZipOutputStream(IOHelper.newOutput(out))) {
|
||||
apply(inputFile, inputFile, output, server, (e) -> false);
|
||||
apply(inputFile, inputFile, output, server, (e) -> false);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
public static void apply(Path inputFile, Path addFile, ZipOutputStream output, LaunchServer srv, Predicate<ZipEntry> excluder) throws IOException {
|
||||
try (ClassMetadataReader reader = new ClassMetadataReader()) {
|
||||
try (ClassMetadataReader reader = new ClassMetadataReader()) {
|
||||
reader.getCp().add(new JarFile(inputFile.toFile()));
|
||||
List<JarFile> libs = srv.launcherBinary.coreLibs.stream().map(e -> {
|
||||
try {
|
||||
return new JarFile(e.toFile());
|
||||
} catch (IOException e1) {
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
try {
|
||||
return new JarFile(e.toFile());
|
||||
} catch (IOException e1) {
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
}).collect(Collectors.toList());
|
||||
libs.addAll(srv.launcherBinary.addonLibs.stream().map(e -> {
|
||||
try {
|
||||
return new JarFile(e.toFile());
|
||||
} catch (IOException e1) {
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
}).collect(Collectors.toList()));
|
||||
try {
|
||||
return new JarFile(e.toFile());
|
||||
} catch (IOException e1) {
|
||||
throw new RuntimeException(e1);
|
||||
}
|
||||
}).collect(Collectors.toList()));
|
||||
try (ZipInputStream input = IOHelper.newZipInput(addFile)) {
|
||||
ZipEntry e = input.getNextEntry();
|
||||
while (e != null) {
|
||||
|
|
|
@ -40,8 +40,8 @@ public Path process(Path inputFile) throws IOException {
|
|||
SessionInfo info = p.createSessionFromConfig();
|
||||
info.setInput(inputFile.toFile());
|
||||
info.setOutput(outputFile.toFile());
|
||||
List<File> libs = srv.launcherBinary.coreLibs.stream().map(e -> e.toFile()).collect(Collectors.toList());
|
||||
libs.addAll(srv.launcherBinary.addonLibs.stream().map(e -> e.toFile()).collect(Collectors.toList()));
|
||||
List<File> libs = srv.launcherBinary.coreLibs.stream().map(Path::toFile).collect(Collectors.toList());
|
||||
libs.addAll(srv.launcherBinary.addonLibs.stream().map(Path::toFile).collect(Collectors.toList()));
|
||||
info.setLibraries(libs);
|
||||
Radon r = new Radon(info);
|
||||
r.run();
|
||||
|
|
|
@ -8,13 +8,13 @@
|
|||
public final class TaskUtil {
|
||||
public static void addCounted(List<LauncherBuildTask> tasks, int count, Predicate<LauncherBuildTask> pred, LauncherBuildTask taskAdd) {
|
||||
List<LauncherBuildTask> indexes = new ArrayList<>();
|
||||
tasks.stream().filter(pred).forEach(e -> indexes.add(e));
|
||||
tasks.stream().filter(pred).forEach(indexes::add);
|
||||
indexes.forEach(e -> tasks.add(tasks.indexOf(e) + count, taskAdd));
|
||||
}
|
||||
|
||||
public static void replaceCounted(List<LauncherBuildTask> tasks, int count, Predicate<LauncherBuildTask> pred, LauncherBuildTask taskRep) {
|
||||
List<LauncherBuildTask> indexes = new ArrayList<>();
|
||||
tasks.stream().filter(pred).forEach(e -> indexes.add(e));
|
||||
tasks.stream().filter(pred).forEach(indexes::add);
|
||||
indexes.forEach(e -> tasks.set(tasks.indexOf(e) + count, taskRep));
|
||||
}
|
||||
|
||||
|
|
|
@ -26,10 +26,8 @@ public String getUsageDescription() {
|
|||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 1);
|
||||
List<HWID> target = server.config.hwidHandler.getHwid(args[0]);
|
||||
for(HWID hwid : target)
|
||||
{
|
||||
if(hwid == null)
|
||||
{
|
||||
for (HWID hwid : target) {
|
||||
if (hwid == null) {
|
||||
LogHelper.error("HWID %s: null", args[0]);
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -35,8 +35,7 @@ public void invoke(String... args) throws Exception {
|
|||
if (args[0].equals("stop")) {
|
||||
handler.close();
|
||||
}
|
||||
if (args[0].equals("eventAll"))
|
||||
{
|
||||
if (args[0].equals("eventAll")) {
|
||||
WebSocketFrameHandler.service.sendObjectAll(new PingEvent());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,7 +38,7 @@ public static void registerCommands(ru.gravit.utils.command.CommandHandler handl
|
|||
basic.registerCommand("loadModule", new LoadModuleCommand(server));
|
||||
basic.registerCommand("modules", new ModulesCommand(server));
|
||||
basic.registerCommand("test", new TestCommand(server));
|
||||
Category basicCategory = new Category(basic,"basic", "Base LaunchServer commands");
|
||||
Category basicCategory = new Category(basic, "basic", "Base LaunchServer commands");
|
||||
handler.registerCategory(basicCategory);
|
||||
|
||||
// Register sync commands
|
||||
|
@ -50,7 +50,7 @@ public static void registerCommands(ru.gravit.utils.command.CommandHandler handl
|
|||
updates.registerCommand("syncBinaries", new SyncBinariesCommand(server));
|
||||
updates.registerCommand("syncUpdates", new SyncUpdatesCommand(server));
|
||||
updates.registerCommand("syncProfiles", new SyncProfilesCommand(server));
|
||||
Category updatesCategory = new Category(updates,"updates", "Update and Sync Management");
|
||||
Category updatesCategory = new Category(updates, "updates", "Update and Sync Management");
|
||||
handler.registerCategory(updatesCategory);
|
||||
|
||||
// Register auth commands
|
||||
|
@ -61,14 +61,14 @@ public static void registerCommands(ru.gravit.utils.command.CommandHandler handl
|
|||
auth.registerCommand("ban", new BanCommand(server));
|
||||
auth.registerCommand("unban", new UnbanCommand(server));
|
||||
auth.registerCommand("getHWID", new GetHWIDCommand(server));
|
||||
Category authCategory = new Category(auth,"auth", "User Management");
|
||||
Category authCategory = new Category(auth, "auth", "User Management");
|
||||
handler.registerCategory(authCategory);
|
||||
|
||||
//Register dump commands
|
||||
BaseCommandCategory dump = new BaseCommandCategory();
|
||||
dump.registerCommand("dumpSessions", new DumpSessionsCommand(server));
|
||||
dump.registerCommand("dumpEntryCache", new DumpEntryCacheCommand(server));
|
||||
Category dumpCategory = new Category(dump,"dump", "Dump runtime data");
|
||||
Category dumpCategory = new Category(dump, "dump", "Dump runtime data");
|
||||
handler.registerCategory(dumpCategory);
|
||||
|
||||
//Register service commands
|
||||
|
@ -86,7 +86,7 @@ public static void registerCommands(ru.gravit.utils.command.CommandHandler handl
|
|||
service.registerCommand("component", new ComponentCommand(server));
|
||||
service.registerCommand("givePermission", new GivePermissionsCommand(server));
|
||||
service.registerCommand("getPermissions", new GetPermissionsCommand(server));
|
||||
Category serviceCategory = new Category(service,"service", "Managing LaunchServer Components");
|
||||
Category serviceCategory = new Category(service, "service", "Managing LaunchServer Components");
|
||||
handler.registerCategory(serviceCategory);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,8 +35,7 @@ public void invoke(String... args) {
|
|||
LogHelper.info("Uptime: %d days %d hours %d minutes %d seconds", days, hour, min, second);
|
||||
LogHelper.info("Uptime (double): %f", (double) JVMHelper.RUNTIME_MXBEAN.getUptime() / 1000);
|
||||
int commands = server.commandHandler.getBaseCategory().commandsMap().size();
|
||||
for(CommandHandler.Category category : server.commandHandler.getCategories())
|
||||
{
|
||||
for (CommandHandler.Category category : server.commandHandler.getCategories()) {
|
||||
commands += category.category.commandsMap().size();
|
||||
}
|
||||
LogHelper.info("Sessions: %d | Modules: %d | Commands: %d(%d categories)", server.sessionManager.getSessions().size(), server.modulesManager.modules.size(), commands, server.commandHandler.getCategories().size() + 1);
|
||||
|
|
|
@ -5,12 +5,12 @@
|
|||
|
||||
public class LaunchServerRuntimeConfig {
|
||||
public String clientToken;
|
||||
public void verify()
|
||||
{
|
||||
if(clientToken == null) LogHelper.error("[RuntimeConfig] clientToken must not be null");
|
||||
|
||||
public void verify() {
|
||||
if (clientToken == null) LogHelper.error("[RuntimeConfig] clientToken must not be null");
|
||||
}
|
||||
public void reset()
|
||||
{
|
||||
|
||||
public void reset() {
|
||||
clientToken = SecurityHelper.randomStringToken();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ protected final void debug(String message, Object... args) {
|
|||
public abstract void reply() throws Exception;
|
||||
|
||||
|
||||
protected static final void writeNoError(HOutput output) throws IOException {
|
||||
protected static void writeNoError(HOutput output) throws IOException {
|
||||
output.writeString("", 0);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -14,8 +14,8 @@ public void registerReconfigurable(String name, Reconfigurable reconfigurable) {
|
|||
VerifyHelper.putIfAbsent(RECONFIGURABLE, name.toLowerCase(), Objects.requireNonNull(reconfigurable, "adapter"),
|
||||
String.format("Reloadable has been already registered: '%s'", name));
|
||||
}
|
||||
public Reconfigurable unregisterReconfigurable(String name)
|
||||
{
|
||||
|
||||
public Reconfigurable unregisterReconfigurable(String name) {
|
||||
return RECONFIGURABLE.remove(name);
|
||||
}
|
||||
|
||||
|
|
|
@ -14,8 +14,8 @@ public void registerReloadable(String name, Reloadable reloadable) {
|
|||
VerifyHelper.putIfAbsent(RELOADABLES, name.toLowerCase(), Objects.requireNonNull(reloadable, "adapter"),
|
||||
String.format("Reloadable has been already registered: '%s'", name.toLowerCase()));
|
||||
}
|
||||
public Reloadable unregisterReloadable(String name)
|
||||
{
|
||||
|
||||
public Reloadable unregisterReloadable(String name) {
|
||||
return RELOADABLES.remove(name);
|
||||
}
|
||||
|
||||
|
|
|
@ -44,15 +44,16 @@ public void initChannel(NioSocketChannel ch) {
|
|||
//p.addLast(new LoggingHandler(LogLevel.INFO));
|
||||
pipeline.addLast(new HttpServerCodec());
|
||||
pipeline.addLast(new HttpObjectAggregator(65536));
|
||||
if (LaunchServer.server.config.netty.ipForwarding) pipeline.addLast(new NettyIpForwardHandler(context));
|
||||
if (LaunchServer.server.config.netty.ipForwarding)
|
||||
pipeline.addLast(new NettyIpForwardHandler(context));
|
||||
pipeline.addLast(new WebSocketServerCompressionHandler());
|
||||
pipeline.addLast(new WebSocketServerProtocolHandler(WEBSOCKET_PATH, null, true));
|
||||
if (LaunchServer.server.config.netty.fileServerEnabled) 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(context));
|
||||
}
|
||||
});
|
||||
if(config.proxy != null && config.proxy.enabled)
|
||||
{
|
||||
if (config.proxy != null && config.proxy.enabled) {
|
||||
LogHelper.info("Connect to main server %s");
|
||||
Request.service = StandartClientWebSocketService.initWebSockets(config.proxy.address, false);
|
||||
AuthRequest authRequest = new AuthRequest(config.proxy.login, config.proxy.password, config.proxy.auth_id, AuthRequest.ConnectTypes.PROXY);
|
||||
|
@ -64,8 +65,8 @@ public void initChannel(NioSocketChannel ch) {
|
|||
}
|
||||
}
|
||||
}
|
||||
public ChannelFuture bind(InetSocketAddress address)
|
||||
{
|
||||
|
||||
public ChannelFuture bind(InetSocketAddress address) {
|
||||
return serverBootstrap.bind(address);
|
||||
}
|
||||
|
||||
|
|
|
@ -19,8 +19,7 @@ public NettyIpForwardHandler(NettyConnectContext context) {
|
|||
|
||||
@Override
|
||||
protected void decode(ChannelHandlerContext ctx, HttpRequest msg, List<Object> out) throws Exception {
|
||||
if(msg instanceof ReferenceCounted)
|
||||
{
|
||||
if (msg instanceof ReferenceCounted) {
|
||||
((ReferenceCounted) msg).retain();
|
||||
}
|
||||
if (context.ip != null) {
|
||||
|
|
|
@ -105,8 +105,7 @@ public void run() {
|
|||
//engine.setUseClientMode(false);
|
||||
WebSocketFrameHandler.server = LaunchServer.server;
|
||||
nettyServer = new LauncherNettyServer();
|
||||
for(LaunchServer.NettyBindAddress address : LaunchServer.server.config.netty.binds)
|
||||
{
|
||||
for (LaunchServer.NettyBindAddress address : LaunchServer.server.config.netty.binds) {
|
||||
nettyServer.bind(new InetSocketAddress(address.address, address.port));
|
||||
}
|
||||
/*
|
||||
|
|
|
@ -28,8 +28,8 @@ public WebSocketFrameHandler(NettyConnectContext context) {
|
|||
static {
|
||||
service.registerResponses();
|
||||
}
|
||||
public void setClient(Client client)
|
||||
{
|
||||
|
||||
public void setClient(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
|
@ -52,11 +52,9 @@ protected void channelRead0(ChannelHandlerContext ctx, WebSocketFrame frame) {
|
|||
frame.content().retain();
|
||||
ctx.channel().writeAndFlush(new PongWebSocketFrame(frame.content()));
|
||||
//return;
|
||||
}
|
||||
else if ((frame instanceof PongWebSocketFrame)) {
|
||||
} else if ((frame instanceof PongWebSocketFrame)) {
|
||||
LogHelper.dev("WebSocket Client received pong");
|
||||
}
|
||||
else if ((frame instanceof CloseWebSocketFrame)) {
|
||||
} else if ((frame instanceof CloseWebSocketFrame)) {
|
||||
ctx.channel().close();
|
||||
} else {
|
||||
String message = "unsupported frame type: " + frame.getClass().getName();
|
||||
|
|
|
@ -63,64 +63,54 @@ public WebSocketService(ChannelGroup channels, LaunchServer server, GsonBuilder
|
|||
private final GsonBuilder gsonBuiler;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) {
|
||||
void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) {
|
||||
String request = frame.text();
|
||||
JsonResponseInterface response = gson.fromJson(request, JsonResponseInterface.class);
|
||||
if(server.config.netty.proxy.enabled)
|
||||
{
|
||||
if(server.config.netty.proxy.requests.contains(response.getType()))
|
||||
{
|
||||
if (server.config.netty.proxy.enabled) {
|
||||
if (server.config.netty.proxy.requests.contains(response.getType())) {
|
||||
|
||||
UUID origRequestUUID = null;
|
||||
if(response instanceof SimpleResponse)
|
||||
{
|
||||
if (response instanceof SimpleResponse) {
|
||||
SimpleResponse simpleResponse = (SimpleResponse) response;
|
||||
simpleResponse.server = server;
|
||||
simpleResponse.service = this;
|
||||
simpleResponse.ctx = ctx;
|
||||
if(ip != null) simpleResponse.ip = ip;
|
||||
if (ip != null) simpleResponse.ip = ip;
|
||||
else simpleResponse.ip = IOHelper.getIP(ctx.channel().remoteAddress());
|
||||
origRequestUUID = simpleResponse.requestUUID;
|
||||
}
|
||||
LogHelper.debug("Proxy %s request", response.getType());
|
||||
if(client.session == 0) client.session = new Random().nextLong();
|
||||
if (client.session == 0) client.session = new Random().nextLong();
|
||||
ProxyRequest proxyRequest = new ProxyRequest(response, client.session);
|
||||
if(response instanceof SimpleResponse)
|
||||
{
|
||||
if (response instanceof SimpleResponse) {
|
||||
((SimpleResponse) response).requestUUID = proxyRequest.requestUUID;
|
||||
}
|
||||
proxyRequest.isCheckSign = client.checkSign;
|
||||
try {
|
||||
ResultInterface result = proxyRequest.request();
|
||||
if(result instanceof AuthRequestEvent)
|
||||
{
|
||||
if (result instanceof AuthRequestEvent) {
|
||||
LogHelper.debug("Client auth params get successful");
|
||||
AuthRequestEvent authRequestEvent = (AuthRequestEvent) result;
|
||||
client.isAuth = true;
|
||||
client.session = authRequestEvent.session;
|
||||
if(authRequestEvent.playerProfile != null) client.username = authRequestEvent.playerProfile.username;
|
||||
if (authRequestEvent.playerProfile != null)
|
||||
client.username = authRequestEvent.playerProfile.username;
|
||||
}
|
||||
if(result instanceof Request && response instanceof SimpleResponse)
|
||||
{
|
||||
if (result instanceof Request && response instanceof SimpleResponse) {
|
||||
((Request) result).requestUUID = origRequestUUID;
|
||||
}
|
||||
sendObject(ctx, result);
|
||||
} catch (RequestException e)
|
||||
{
|
||||
} catch (RequestException e) {
|
||||
sendObject(ctx, new ErrorRequestEvent(e.getMessage()));
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
RequestEvent event;
|
||||
if(server.config.netty.sendExceptionEnabled)
|
||||
{
|
||||
if (server.config.netty.sendExceptionEnabled) {
|
||||
event = new ExceptionEvent(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
event = new ErrorRequestEvent("Fatal server error. Contact administrator");
|
||||
}
|
||||
if(response instanceof SimpleResponse)
|
||||
{
|
||||
if (response instanceof SimpleResponse) {
|
||||
event.requestUUID = ((SimpleResponse) response).requestUUID;
|
||||
}
|
||||
sendObject(ctx, event);
|
||||
|
@ -128,17 +118,16 @@ void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client,
|
|||
return;
|
||||
}
|
||||
}
|
||||
process(ctx,response, client, ip);
|
||||
process(ctx, response, client, ip);
|
||||
}
|
||||
void process(ChannelHandlerContext ctx, JsonResponseInterface response, Client client, String ip)
|
||||
{
|
||||
if(response instanceof SimpleResponse)
|
||||
{
|
||||
|
||||
void process(ChannelHandlerContext ctx, JsonResponseInterface response, Client client, String ip) {
|
||||
if (response instanceof SimpleResponse) {
|
||||
SimpleResponse simpleResponse = (SimpleResponse) response;
|
||||
simpleResponse.server = server;
|
||||
simpleResponse.service = this;
|
||||
simpleResponse.ctx = ctx;
|
||||
if(ip != null) simpleResponse.ip = ip;
|
||||
if (ip != null) simpleResponse.ip = ip;
|
||||
else simpleResponse.ip = IOHelper.getIP(ctx.channel().remoteAddress());
|
||||
}
|
||||
try {
|
||||
|
@ -146,16 +135,12 @@ void process(ChannelHandlerContext ctx, JsonResponseInterface response, Client c
|
|||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
RequestEvent event;
|
||||
if(server.config.netty.sendExceptionEnabled)
|
||||
{
|
||||
if (server.config.netty.sendExceptionEnabled) {
|
||||
event = new ExceptionEvent(e);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
event = new ErrorRequestEvent("Fatal server error. Contact administrator");
|
||||
}
|
||||
if(response instanceof SimpleResponse)
|
||||
{
|
||||
if (response instanceof SimpleResponse) {
|
||||
event.requestUUID = ((SimpleResponse) response).requestUUID;
|
||||
}
|
||||
sendObject(ctx, event);
|
||||
|
@ -204,15 +189,13 @@ public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) {
|
|||
}
|
||||
|
||||
public void sendObjectAll(Object obj) {
|
||||
for(Channel ch : channels)
|
||||
{
|
||||
for (Channel ch : channels) {
|
||||
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, ResultInterface.class)));
|
||||
}
|
||||
}
|
||||
|
||||
public void sendObjectAll(Object obj, Type type) {
|
||||
for(Channel ch : channels)
|
||||
{
|
||||
for (Channel ch : channels) {
|
||||
ch.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,18 +15,18 @@ public abstract class SimpleResponse implements JsonResponseInterface {
|
|||
public transient WebSocketService service;
|
||||
public transient ChannelHandlerContext ctx;
|
||||
public transient String ip;
|
||||
public void sendResult(RequestEvent result)
|
||||
{
|
||||
|
||||
public void sendResult(RequestEvent result) {
|
||||
result.requestUUID = requestUUID;
|
||||
service.sendObject(ctx, result);
|
||||
}
|
||||
public void sendResultAndClose(RequestEvent result)
|
||||
{
|
||||
|
||||
public void sendResultAndClose(RequestEvent result) {
|
||||
result.requestUUID = requestUUID;
|
||||
service.sendObjectAndClose(ctx, result);
|
||||
}
|
||||
public void sendError(String errorMessage)
|
||||
{
|
||||
|
||||
public void sendError(String errorMessage) {
|
||||
ErrorRequestEvent event = new ErrorRequestEvent(errorMessage);
|
||||
event.requestUUID = requestUUID;
|
||||
service.sendObject(ctx, event);
|
||||
|
|
|
@ -9,9 +9,10 @@ public class ProxyCommandResponse extends SimpleResponse {
|
|||
public JsonResponseInterface response;
|
||||
public long session;
|
||||
public boolean isCheckSign;
|
||||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
if(!client.proxy) {
|
||||
if (!client.proxy) {
|
||||
sendError("Proxy server error");
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -61,7 +61,7 @@ public String getType() {
|
|||
public void execute(ChannelHandlerContext ctx, Client clientData) throws Exception {
|
||||
try {
|
||||
AuthRequestEvent result = new AuthRequestEvent();
|
||||
if ((authType == null || authType == ConnectTypes.CLIENT) && ( clientData == null || !clientData.checkSign )) {
|
||||
if ((authType == null || authType == ConnectTypes.CLIENT) && (clientData == null || !clientData.checkSign)) {
|
||||
AuthProvider.authError("Don't skip Launcher Update");
|
||||
return;
|
||||
}
|
||||
|
@ -113,21 +113,18 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
|||
clientData.updateAuth();
|
||||
result.accessToken = aresult.accessToken;
|
||||
result.permissions = clientData.permissions;
|
||||
if(getSession)
|
||||
{
|
||||
if(clientData.session == 0) {
|
||||
if (getSession) {
|
||||
if (clientData.session == 0) {
|
||||
clientData.session = random.nextLong();
|
||||
LaunchServer.server.sessionManager.addClient(clientData);
|
||||
}
|
||||
result.session = clientData.session;
|
||||
}
|
||||
if(initProxy)
|
||||
{
|
||||
if(!clientData.permissions.canProxy) throw new AuthException("initProxy not allow");
|
||||
if (initProxy) {
|
||||
if (!clientData.permissions.canProxy) throw new AuthException("initProxy not allow");
|
||||
clientData.proxy = true;
|
||||
}
|
||||
if(LaunchServer.server.config.protectHandler.allowGetAccessToken(context))
|
||||
{
|
||||
if (LaunchServer.server.config.protectHandler.allowGetAccessToken(context)) {
|
||||
UUID uuid = pair.handler.auth(aresult);
|
||||
result.playerProfile = ProfileByUUIDResponse.getProfile(LaunchServer.server, uuid, aresult.username, client, clientData.auth.textureProvider);
|
||||
LogHelper.debug("Auth: %s accessToken %s uuid: %s", login, result.accessToken, uuid.toString());
|
||||
|
@ -137,6 +134,7 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
|||
sendError(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public static class AuthContext {
|
||||
public AuthContext(long session, String login, int password_lenght, String customText, String client, String hwid, String ip, boolean isServerAuth) {
|
||||
this.session = session;
|
||||
|
|
|
@ -19,8 +19,7 @@ public String getType() {
|
|||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||
List<GetAvailabilityAuthRequestEvent.AuthAvailability> list = new ArrayList<>();
|
||||
for(AuthProviderPair pair : LaunchServer.server.config.auth)
|
||||
{
|
||||
for (AuthProviderPair pair : LaunchServer.server.config.auth) {
|
||||
list.add(new GetAvailabilityAuthRequestEvent.AuthAvailability(pair.name, pair.displayName));
|
||||
}
|
||||
sendResult(new GetAvailabilityAuthRequestEvent(list));
|
||||
|
|
|
@ -18,17 +18,16 @@ public class JoinServerResponse extends SimpleResponse {
|
|||
public String getType() {
|
||||
return "joinServer";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||
boolean success;
|
||||
try {
|
||||
server.authHookManager.joinServerHook.hook(this, client);
|
||||
if(client.auth == null)
|
||||
{
|
||||
if (client.auth == null) {
|
||||
LogHelper.warning("Client auth is null. Using default.");
|
||||
success = LaunchServer.server.config.getAuthProviderPair().handler.joinServer(username, accessToken, serverID);
|
||||
}
|
||||
else success = client.auth.handler.joinServer(username, accessToken, serverID);
|
||||
} else success = client.auth.handler.joinServer(username, accessToken, serverID);
|
||||
LogHelper.debug("joinServer: %s accessToken: %s serverID: %s", username, accessToken, serverID);
|
||||
} catch (AuthException | HookException e) {
|
||||
sendError(e.getMessage());
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
public class RestoreSessionResponse extends SimpleResponse {
|
||||
@LauncherNetworkAPI
|
||||
public long session;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "restoreSession";
|
||||
|
@ -19,8 +20,7 @@ public String getType() {
|
|||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||
Client rClient = LaunchServer.server.sessionManager.getClient(session);
|
||||
if(rClient == null)
|
||||
{
|
||||
if (rClient == null) {
|
||||
sendError("Session invalid");
|
||||
}
|
||||
WebSocketFrameHandler frameHandler = ctx.pipeline().get(WebSocketFrameHandler.class);
|
||||
|
|
|
@ -26,8 +26,7 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
|||
}
|
||||
try {
|
||||
server.authHookManager.setProfileHook.hook(this, client);
|
||||
} catch (HookException e)
|
||||
{
|
||||
} catch (HookException e) {
|
||||
sendError(e.getMessage());
|
||||
}
|
||||
Collection<ClientProfile> profiles = LaunchServer.server.getProfiles();
|
||||
|
|
|
@ -29,12 +29,10 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
|||
result.playerProfiles = new PlayerProfile[list.length];
|
||||
for (int i = 0; i < list.length; ++i) {
|
||||
UUID uuid;
|
||||
if(client.auth == null)
|
||||
{
|
||||
if (client.auth == null) {
|
||||
LogHelper.warning("Client auth is null. Using default.");
|
||||
uuid = LaunchServer.server.config.getAuthProviderPair().handler.usernameToUUID(list[i].username);
|
||||
}
|
||||
else uuid = client.auth.handler.usernameToUUID(list[i].username);
|
||||
} else uuid = client.auth.handler.usernameToUUID(list[i].username);
|
||||
result.playerProfiles[i] = ProfileByUUIDResponse.getProfile(LaunchServer.server, uuid, list[i].username, list[i].client, client.auth.textureProvider);
|
||||
}
|
||||
sendResult(result);
|
||||
|
|
|
@ -48,12 +48,10 @@ public String getType() {
|
|||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
String username;
|
||||
if(client.auth == null)
|
||||
{
|
||||
if (client.auth == null) {
|
||||
LogHelper.warning("Client auth is null. Using default.");
|
||||
username = LaunchServer.server.config.getAuthProviderPair().handler.uuidToUsername(uuid);
|
||||
}
|
||||
else username = client.auth.handler.uuidToUsername(uuid);
|
||||
} else username = client.auth.handler.uuidToUsername(uuid);
|
||||
sendResult(new ProfileByUUIDRequestEvent(getProfile(LaunchServer.server, uuid, username, this.client, client.auth.textureProvider)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,12 +23,10 @@ public String getType() {
|
|||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||
UUID uuid;
|
||||
if(client.auth == null)
|
||||
{
|
||||
if (client.auth == null) {
|
||||
LogHelper.warning("Client auth is null. Using default.");
|
||||
uuid = LaunchServer.server.config.getAuthProviderPair().handler.usernameToUUID(username);
|
||||
}
|
||||
else uuid = client.auth.handler.usernameToUUID(username);
|
||||
} else uuid = client.auth.handler.usernameToUUID(username);
|
||||
sendResult(new ProfileByUsernameRequestEvent(getProfile(LaunchServer.server, uuid, username, this.client, client.auth.textureProvider)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ public String getType() {
|
|||
@Override
|
||||
public void execute(ChannelHandlerContext ctx, Client client) {
|
||||
boolean success = LaunchServer.server.config.protectHandler.verifyClientSecureToken(secureToken, client.verifyToken);
|
||||
if(success) client.isSecure = true;
|
||||
if (success) client.isSecure = true;
|
||||
sendResult(new VerifySecureTokenRequestEvent(success));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,13 +34,18 @@ public void execute(ChannelHandlerContext ctx, Client client) {
|
|||
}
|
||||
}
|
||||
SignedObjectHolder<HashedDir> dir = LaunchServer.server.updatesDirMap.get(dirName);
|
||||
if(dir == null)
|
||||
{
|
||||
if (dir == null) {
|
||||
service.sendObject(ctx, new ErrorRequestEvent(String.format("Directory %s not found", dirName)));
|
||||
return;
|
||||
}
|
||||
String url = LaunchServer.server.config.netty.downloadURL.replace("%dirname%",dirName);
|
||||
if(server.config.netty.bindings.get(dirName) != null) url = server.config.netty.bindings.get(dirName);
|
||||
service.sendObject(ctx, new UpdateRequestEvent(dir.object, url));
|
||||
String url = LaunchServer.server.config.netty.downloadURL.replace("%dirname%", dirName);
|
||||
boolean zip = false;
|
||||
if (server.config.netty.bindings.get(dirName) != null)
|
||||
{
|
||||
LaunchServer.NettyUpdatesBind bind = server.config.netty.bindings.get(dirName);
|
||||
url = bind.url;
|
||||
zip = bind.zip;
|
||||
}
|
||||
service.sendObject(ctx, new UpdateRequestEvent(dir.object, url, zip));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,7 +20,7 @@ public static void main(String[] args) throws IOException {
|
|||
LogHelper.warning("Permission canAdmin not found");
|
||||
}
|
||||
try {
|
||||
Class.forName("jline.Terminal");
|
||||
Class.forName("org.jline.terminal.Terminal");
|
||||
|
||||
// JLine2 available
|
||||
commandHandler = new JLineCommandHandler();
|
||||
|
@ -33,8 +33,8 @@ public static void main(String[] args) throws IOException {
|
|||
LogHelper.info("CommandHandler started. Use 'exit' to exit this console");
|
||||
commandHandler.run();
|
||||
}
|
||||
public static void registerCommands()
|
||||
{
|
||||
|
||||
public static void registerCommands() {
|
||||
commandHandler.registerCommand("help", new HelpCommand(commandHandler));
|
||||
commandHandler.registerCommand("exit", new ExitCommand());
|
||||
commandHandler.registerCommand("logListener", new LogListenerCommand());
|
||||
|
|
|
@ -19,6 +19,6 @@ public String getUsageDescription() {
|
|||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
ExecCommandRequestEvent request = new ExecCommandRequest(String.join(" ")).request();
|
||||
if(!request.success) LogHelper.error("Error executing command");
|
||||
if (!request.success) LogHelper.error("Error executing command");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public class LogListenerCommand extends Command {
|
||||
public class LogListenerRequest implements RequestInterface
|
||||
{
|
||||
public class LogListenerRequest implements RequestInterface {
|
||||
@LauncherNetworkAPI
|
||||
public LogHelper.OutputTypes outputType;
|
||||
|
||||
|
@ -22,6 +21,7 @@ public String getType() {
|
|||
return "addLogListener";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArgsDescription() {
|
||||
return null;
|
||||
|
@ -38,8 +38,7 @@ public void invoke(String... args) throws Exception {
|
|||
Request.service.sendObject(new LogListenerRequest(LogHelper.JANSI ? LogHelper.OutputTypes.JANSI : LogHelper.OutputTypes.PLAIN));
|
||||
LogHelper.info("Add log handler");
|
||||
Request.service.registerHandler((result) -> {
|
||||
if(result instanceof LogEvent)
|
||||
{
|
||||
if (result instanceof LogEvent) {
|
||||
System.out.println(((LogEvent) result).string);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -28,11 +28,11 @@
|
|||
}
|
||||
|
||||
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'
|
||||
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 {
|
||||
|
|
|
@ -45,7 +45,6 @@ function initLoginScene() {
|
|||
var loginLayout = loginPane.lookup("#layout");
|
||||
loginPaneLayout = loginLayout;
|
||||
|
||||
|
||||
loginField = pane.lookup("#login");
|
||||
loginField.setOnMouseMoved(function(event){rootPane.fireEvent(event)});
|
||||
loginField.setOnAction(goAuth);
|
||||
|
@ -203,7 +202,7 @@ function goAuth(event) {
|
|||
var rsaPassword = null;
|
||||
var auth = authOptions.getSelectionModel().getSelectedItem();
|
||||
if (auth === null) {
|
||||
return;
|
||||
return;
|
||||
}
|
||||
if (!passwordField.isDisable()) {
|
||||
var password = passwordField.getText();
|
||||
|
@ -419,7 +418,6 @@ var overlay = {
|
|||
|
||||
dimPane.setVisible(true);
|
||||
dimPane.toFront();
|
||||
|
||||
loginPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(10));
|
||||
serverPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(10));
|
||||
fade(dimPane, 0.0, 0.0, 1.0, function(event) {
|
||||
|
@ -441,7 +439,6 @@ var overlay = {
|
|||
|
||||
authPane.setDisable(false);
|
||||
rootPane.requestFocus();
|
||||
|
||||
loginPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(0));
|
||||
serverPaneLayout.setEffect(new javafx.scene.effect.GaussianBlur(0));
|
||||
overlay.current = null;
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<title>Offline-режим</title>
|
||||
</head>
|
||||
|
||||
<body style="color:red">
|
||||
<h2>Offline-режим</h2>
|
||||
Лаунчер запущен в Offline-режиме. В этом режиме Вы можете запустить любой ранее загруженный клиент
|
||||
с любым именем пользователя, при этом вход на серверы с авторизацией, а так же система скинов и плащей <b>может не работать</b>.
|
||||
Скорее всего, проблема вызвана сбоем на сервере или неполадками в интернет-подключении.
|
||||
Проверьте состояние интернет-подключения или обратитесь к администратору сервера.
|
||||
</body>
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
<title>Offline-режим</title>
|
||||
</head>
|
||||
|
||||
<body style="color:red">
|
||||
<h2>Offline-режим</h2>
|
||||
Лаунчер запущен в Offline-режиме. В этом режиме Вы можете запустить любой ранее загруженный клиент
|
||||
с любым именем пользователя, при этом вход на серверы с авторизацией, а так же система скинов и плащей <b>может не
|
||||
работать</b>.
|
||||
Скорее всего, проблема вызвана сбоем на сервере или неполадками в интернет-подключении.
|
||||
Проверьте состояние интернет-подключения или обратитесь к администратору сервера.
|
||||
</body>
|
||||
</html>
|
|
@ -8,17 +8,20 @@
|
|||
|
||||
<!-- DrLeonardo Design -->
|
||||
|
||||
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="693.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="693.0" xmlns="http://javafx.com/javafx/8.0.201"
|
||||
xmlns:fx="http://javafx.com/fxml/1">
|
||||
<stylesheets>
|
||||
<URL value="@debug.css" />
|
||||
<URL value="@../../styles.css" />
|
||||
<URL value="@debug.css"/>
|
||||
<URL value="@../../styles.css"/>
|
||||
</stylesheets>
|
||||
|
||||
<!-- Debug controls -->
|
||||
<JFXTextArea fx:id="output" focusColor="#5fd97a" prefHeight="450.0" prefWidth="693.0">
|
||||
<padding>
|
||||
<Insets left="10.0" right="10.0" />
|
||||
</padding></JFXTextArea>
|
||||
<JFXButton fx:id="copy" defaultButton="true" layoutX="373.0" layoutY="415.0" prefHeight="30.0" prefWidth="100.0" text="Копировать" />
|
||||
<JFXButton fx:id="action" layoutX="533.0" layoutY="415.0" prefHeight="25.0" prefWidth="150.0" text="Убить" />
|
||||
<padding>
|
||||
<Insets left="10.0" right="10.0"/>
|
||||
</padding>
|
||||
</JFXTextArea>
|
||||
<JFXButton fx:id="copy" defaultButton="true" layoutX="373.0" layoutY="415.0" prefHeight="30.0" prefWidth="100.0"
|
||||
text="Копировать"/>
|
||||
<JFXButton fx:id="action" layoutX="533.0" layoutY="415.0" prefHeight="25.0" prefWidth="150.0" text="Убить"/>
|
||||
</Pane>
|
||||
|
|
|
@ -7,13 +7,15 @@
|
|||
|
||||
<!-- DrLeonardo Design | Fixes by Yaroslavik -->
|
||||
|
||||
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="692.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<children>
|
||||
<!-- Description -->
|
||||
<Label fx:id="description" alignment="CENTER" contentDisplay="CENTER" layoutX="205.0" layoutY="328.0" prefHeight="87.0" prefWidth="283.0" text="..." textAlignment="CENTER" />
|
||||
<JFXSpinner fx:id="spinner" layoutX="291.0" layoutY="165.0" prefHeight="120.0" prefWidth="110.0" />
|
||||
</children>
|
||||
<stylesheets>
|
||||
<URL value="@processing.css" />
|
||||
</stylesheets>
|
||||
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="692.0" xmlns="http://javafx.com/javafx/8.0.201"
|
||||
xmlns:fx="http://javafx.com/fxml/1">
|
||||
<children>
|
||||
<!-- Description -->
|
||||
<Label fx:id="description" alignment="CENTER" contentDisplay="CENTER" layoutX="205.0" layoutY="328.0"
|
||||
prefHeight="87.0" prefWidth="283.0" text="..." textAlignment="CENTER"/>
|
||||
<JFXSpinner fx:id="spinner" layoutX="291.0" layoutY="165.0" prefHeight="120.0" prefWidth="110.0"/>
|
||||
</children>
|
||||
<stylesheets>
|
||||
<URL value="@processing.css"/>
|
||||
</stylesheets>
|
||||
</Pane>
|
||||
|
|
|
@ -13,42 +13,60 @@
|
|||
|
||||
<!-- DrLeonardo Design -->
|
||||
|
||||
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="693.0" xmlns="http://javafx.com/javafx/8.0.201" xmlns:fx="http://javafx.com/fxml/1">
|
||||
<children>
|
||||
<Pane id="holder" prefHeight="450.0" prefWidth="694.0">
|
||||
<children>
|
||||
<JFXCheckBox fx:id="autoEnter" checkedColor="#5fd97a" layoutX="14.0" layoutY="137.0" text="Автовход на сервер" unCheckedColor="#909090" />
|
||||
<Text fill="#8c8c8c" layoutX="40.0" layoutY="153.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Включение авто-входа означает что вы сразу после загрузки клиента попадете на сервер" wrappingWidth="636.9999872148037" y="15.0" />
|
||||
<JFXCheckBox fx:id="fullScreen" checkedColor="#5fd97a" layoutX="13.0" layoutY="260.0" text="Клиент в полный экран" unCheckedColor="#909090" />
|
||||
<Text fill="#8c8c8c" layoutX="40.0" layoutY="277.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Включение данной функции позволяет запустить игру сразу в полноэкранном режиме" wrappingWidth="636.9999872148037" y="15.0" />
|
||||
<JFXCheckBox id="debug" checkedColor="#5fd97a" layoutX="13.0" layoutY="193.0" text="Режим Отладки" unCheckedColor="#909090" />
|
||||
<Text fill="#8c8c8c" layoutX="40.0" layoutY="208.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Режим отладки позволяет просмотреть лог запуска и работы программы в реальном времени прямо из лаунчера, что упрощает поиск нужной информации" wrappingWidth="637.0000016447157" y="15.0" />
|
||||
<TextFlow layoutX="126.0" layoutY="15.0" prefHeight="16.0" prefWidth="112.0">
|
||||
<Text fx:id="ramLabel" />
|
||||
</TextFlow>
|
||||
<JFXButton fx:id="deleteDir" layoutX="370.0" layoutY="380.0" prefHeight="25.0" prefWidth="245.0" text="Удалить клиенты" textAlignment="CENTER" wrapText="true" />
|
||||
<JFXButton fx:id="changeDir" layoutY="419.0" prefHeight="30.0" prefWidth="200.0" text="Сменить директорию загрузки" textAlignment="CENTER" wrapText="true" />
|
||||
<Hyperlink id="dirLabel" alignment="BASELINE_LEFT" layoutX="201.0" layoutY="420.0" prefHeight="30.0" prefWidth="493.0" text="C:/Users" />
|
||||
<JFXButton fx:id="apply" defaultButton="true" layoutX="530.0" layoutY="380.0" prefHeight="23.0" prefWidth="100.0" text="Применить" />
|
||||
<Text layoutX="16.0" layoutY="28.0">Выделение памяти: </Text>
|
||||
<JFXSlider fx:id="ramSlider" layoutX="14.0" layoutY="76.0" prefHeight="14.0" prefWidth="663.0" />
|
||||
<Pane fx:id="transferDialog" prefHeight="425.0" prefWidth="694.0" visible="false">
|
||||
<children>
|
||||
<Text fill="WHITE" layoutX="147.0" layoutY="198.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Перенести все данные в новую директорию?" wrappingWidth="400.13671875">
|
||||
<font>
|
||||
<Font size="19.0" />
|
||||
</font>
|
||||
</Text>
|
||||
<JFXButton fx:id="applyTransfer" layoutX="165.0" layoutY="226.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="124.0" text="Да, перенести!" />
|
||||
<JFXButton fx:id="cancelTransfer" layoutX="379.0" layoutY="226.0" mnemonicParsing="false" prefHeight="25.0" prefWidth="124.0" text="Нет, не нужно." />
|
||||
</children>
|
||||
</Pane>
|
||||
<Line endX="594.0" layoutX="100.0" layoutY="420.0" startX="-100.0" stroke="#5b3636" styleClass="lineHead" />
|
||||
</children>
|
||||
</Pane>
|
||||
</children>
|
||||
<stylesheets>
|
||||
<URL value="@settings.css" />
|
||||
<URL value="@../../styles.css" />
|
||||
</stylesheets>
|
||||
<Pane fx:id="overlay" prefHeight="450.0" prefWidth="693.0" xmlns="http://javafx.com/javafx/8.0.201"
|
||||
xmlns:fx="http://javafx.com/fxml/1">
|
||||
<children>
|
||||
<Pane id="holder" prefHeight="450.0" prefWidth="694.0">
|
||||
<children>
|
||||
<JFXCheckBox fx:id="autoEnter" checkedColor="#5fd97a" layoutX="14.0" layoutY="137.0"
|
||||
text="Автовход на сервер" unCheckedColor="#909090"/>
|
||||
<Text fill="#8c8c8c" layoutX="40.0" layoutY="153.0" strokeType="OUTSIDE" strokeWidth="0.0"
|
||||
text="Включение авто-входа означает что вы сразу после загрузки клиента попадете на сервер"
|
||||
wrappingWidth="636.9999872148037" y="15.0"/>
|
||||
<JFXCheckBox fx:id="fullScreen" checkedColor="#5fd97a" layoutX="13.0" layoutY="260.0"
|
||||
text="Клиент в полный экран" unCheckedColor="#909090"/>
|
||||
<Text fill="#8c8c8c" layoutX="40.0" layoutY="277.0" strokeType="OUTSIDE" strokeWidth="0.0"
|
||||
text="Включение данной функции позволяет запустить игру сразу в полноэкранном режиме"
|
||||
wrappingWidth="636.9999872148037" y="15.0"/>
|
||||
<JFXCheckBox id="debug" checkedColor="#5fd97a" layoutX="13.0" layoutY="193.0" text="Режим Отладки"
|
||||
unCheckedColor="#909090"/>
|
||||
<Text fill="#8c8c8c" layoutX="40.0" layoutY="208.0" strokeType="OUTSIDE" strokeWidth="0.0"
|
||||
text="Режим отладки позволяет просмотреть лог запуска и работы программы в реальном времени прямо из лаунчера, что упрощает поиск нужной информации"
|
||||
wrappingWidth="637.0000016447157" y="15.0"/>
|
||||
<TextFlow layoutX="126.0" layoutY="15.0" prefHeight="16.0" prefWidth="112.0">
|
||||
<Text fx:id="ramLabel"/>
|
||||
</TextFlow>
|
||||
<JFXButton fx:id="deleteDir" layoutX="370.0" layoutY="380.0" prefHeight="25.0" prefWidth="245.0"
|
||||
text="Удалить клиенты" textAlignment="CENTER" wrapText="true"/>
|
||||
<JFXButton fx:id="changeDir" layoutY="419.0" prefHeight="30.0" prefWidth="200.0"
|
||||
text="Сменить директорию загрузки" textAlignment="CENTER" wrapText="true"/>
|
||||
<Hyperlink id="dirLabel" alignment="BASELINE_LEFT" layoutX="201.0" layoutY="420.0" prefHeight="30.0"
|
||||
prefWidth="493.0" text="C:/Users"/>
|
||||
<JFXButton fx:id="apply" defaultButton="true" layoutX="530.0" layoutY="380.0" prefHeight="23.0"
|
||||
prefWidth="100.0" text="Применить"/>
|
||||
<Text layoutX="16.0" layoutY="28.0">Выделение памяти:</Text>
|
||||
<JFXSlider fx:id="ramSlider" layoutX="14.0" layoutY="76.0" prefHeight="14.0" prefWidth="663.0"/>
|
||||
<Pane fx:id="transferDialog" prefHeight="425.0" prefWidth="694.0" visible="false">
|
||||
<children>
|
||||
<Text fill="WHITE" layoutX="147.0" layoutY="198.0" strokeType="OUTSIDE" strokeWidth="0.0"
|
||||
text="Перенести все данные в новую директорию?" wrappingWidth="400.13671875">
|
||||
<font>
|
||||
<Font size="19.0"/>
|
||||
</font>
|
||||
</Text>
|
||||
<JFXButton fx:id="applyTransfer" layoutX="165.0" layoutY="226.0" mnemonicParsing="false"
|
||||
prefHeight="25.0" prefWidth="124.0" text="Да, перенести!"/>
|
||||
<JFXButton fx:id="cancelTransfer" layoutX="379.0" layoutY="226.0" mnemonicParsing="false"
|
||||
prefHeight="25.0" prefWidth="124.0" text="Нет, не нужно."/>
|
||||
</children>
|
||||
</Pane>
|
||||
<Line endX="594.0" layoutX="100.0" layoutY="420.0" startX="-100.0" stroke="#5b3636"
|
||||
styleClass="lineHead"/>
|
||||
</children>
|
||||
</Pane>
|
||||
</children>
|
||||
<stylesheets>
|
||||
<URL value="@settings.css"/>
|
||||
<URL value="@../../styles.css"/>
|
||||
</stylesheets>
|
||||
</Pane>
|
||||
|
|
|
@ -15,36 +15,40 @@
|
|||
<children>
|
||||
<Pane fx:id="bar" layoutX="692.0" prefHeight="425.0" prefWidth="43.0" styleClass="bar">
|
||||
<children>
|
||||
<JFXButton id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" ripplerFill="#646464" text="" textAlignment="CENTER">
|
||||
<JFXButton id="hide" alignment="CENTER" contentDisplay="CENTER" layoutY="45.0" ripplerFill="#646464"
|
||||
text="" textAlignment="CENTER">
|
||||
<graphic>
|
||||
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER" />
|
||||
<MaterialDesignIconView fill="WHITE" glyphName="MINUS" size="30" textAlignment="CENTER"/>
|
||||
</graphic>
|
||||
</JFXButton>
|
||||
<JFXButton id="close" alignment="CENTER" contentDisplay="CENTER" ripplerFill="#fb8c8c" text="" textAlignment="CENTER">
|
||||
<JFXButton id="close" alignment="CENTER" contentDisplay="CENTER" ripplerFill="#fb8c8c" text=""
|
||||
textAlignment="CENTER">
|
||||
<graphic>
|
||||
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER" />
|
||||
<MaterialDesignIconView fill="WHITE" glyphName="CLOSE" size="30" textAlignment="CENTER"/>
|
||||
</graphic>
|
||||
</JFXButton>
|
||||
</children>
|
||||
</Pane>
|
||||
<JFXTextArea fx:id="output" focusColor="#d8d8d8" prefHeight="419.0" prefWidth="692.0" unFocusColor="#ffffff00">
|
||||
<padding>
|
||||
<Insets left="10.0" top="10.0" />
|
||||
<Insets left="10.0" top="10.0"/>
|
||||
</padding>
|
||||
</JFXTextArea>
|
||||
<JFXTextField fx:id="textField" focusColor="#909090" layoutY="420.0" prefHeight="30.0" prefWidth="543.0" promptText="Введите команду..." unFocusColor="#ffffff00">
|
||||
<JFXTextField fx:id="textField" focusColor="#909090" layoutY="420.0" prefHeight="30.0" prefWidth="543.0"
|
||||
promptText="Введите команду..." unFocusColor="#ffffff00">
|
||||
<opaqueInsets>
|
||||
<Insets />
|
||||
<Insets/>
|
||||
</opaqueInsets>
|
||||
<padding>
|
||||
<Insets left="10.0" />
|
||||
<Insets left="10.0"/>
|
||||
</padding>
|
||||
</JFXTextField>
|
||||
<JFXButton fx:id="send" defaultButton="true" layoutX="542.0" layoutY="420.0" prefHeight="30.0" prefWidth="147.0" ripplerFill="WHITE" text="Выполнить" />
|
||||
<Line endX="594.0" layoutX="98.0" layoutY="420.0" startX="-100.0" stroke="#5b3636" styleClass="lineHead" />
|
||||
<JFXButton fx:id="send" defaultButton="true" layoutX="542.0" layoutY="420.0" prefHeight="30.0" prefWidth="147.0"
|
||||
ripplerFill="WHITE" text="Выполнить"/>
|
||||
<Line endX="594.0" layoutX="98.0" layoutY="420.0" startX="-100.0" stroke="#5b3636" styleClass="lineHead"/>
|
||||
</children>
|
||||
<stylesheets>
|
||||
<URL value="@../../styles.css" />
|
||||
<URL value="@../../overlay/debug/debug.css" />
|
||||
<URL value="@../../styles.css"/>
|
||||
<URL value="@../../overlay/debug/debug.css"/>
|
||||
</stylesheets>
|
||||
</Pane>
|
||||
|
|
|
@ -3,6 +3,7 @@ Button, CheckBox, ComboBox, RadioButton {
|
|||
-fx-cursor: hand;
|
||||
}
|
||||
|
||||
|
||||
/* Backgrounds */
|
||||
#layout {
|
||||
-fx-background-color: transparent;
|
||||
|
|
|
@ -27,27 +27,22 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
|
|||
EnvHelper.checkDangerousParams();
|
||||
LauncherConfig config = Launcher.getConfig();
|
||||
LogHelper.info("Launcher for project %s", config.projectname);
|
||||
if(config.environment.equals(LauncherConfig.LauncherEnvironment.PROD))
|
||||
{
|
||||
if(System.getProperty(LogHelper.DEBUG_PROPERTY) != null)
|
||||
{
|
||||
if (config.environment.equals(LauncherConfig.LauncherEnvironment.PROD)) {
|
||||
if (System.getProperty(LogHelper.DEBUG_PROPERTY) != null) {
|
||||
LogHelper.warning("Found -Dlauncher.debug=true");
|
||||
}
|
||||
if(System.getProperty(LogHelper.STACKTRACE_PROPERTY) != null)
|
||||
{
|
||||
if (System.getProperty(LogHelper.STACKTRACE_PROPERTY) != null) {
|
||||
LogHelper.warning("Found -Dlauncher.stacktrace=true");
|
||||
}
|
||||
LogHelper.info("Debug mode disabled (found env PRODUCTION)");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
LogHelper.info("If need debug output use -Dlauncher.debug=true");
|
||||
LogHelper.info("If need stacktrace output use -Dlauncher.stacktrace=true");
|
||||
if(LogHelper.isDebugEnabled()) waitProcess = true;
|
||||
if (LogHelper.isDebugEnabled()) waitProcess = true;
|
||||
}
|
||||
LogHelper.info("Restart Launcher with JavaAgent...");
|
||||
ProcessBuilder processBuilder = new ProcessBuilder();
|
||||
if(waitProcess) processBuilder.inheritIO();
|
||||
if (waitProcess) processBuilder.inheritIO();
|
||||
Path javaBin = IOHelper.resolveJavaBin(Paths.get(System.getProperty("java.home")));
|
||||
List<String> args = new LinkedList<>();
|
||||
args.add(javaBin.toString());
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.InsnNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import ru.gravit.launcher.utils.NativeJVMHalt;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
|
@ -20,7 +19,8 @@
|
|||
import java.util.List;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
import static org.objectweb.asm.Opcodes.*;
|
||||
import static org.objectweb.asm.Opcodes.ACONST_NULL;
|
||||
import static org.objectweb.asm.Opcodes.ARETURN;
|
||||
|
||||
@LauncherAPI
|
||||
public final class LauncherAgent {
|
||||
|
@ -37,28 +37,28 @@ public boolean isAgentStarted() {
|
|||
}
|
||||
|
||||
public static void premain(String agentArgument, Instrumentation instrumentation) {
|
||||
System.out.println("Launcher Agent");
|
||||
System.out.println("Launcher Agent");
|
||||
inst = instrumentation;
|
||||
SafeExitJVMLegacy.class.getName();
|
||||
SafeExitJVM.class.getName();
|
||||
NativeJVMHalt.class.getName();
|
||||
SafeExitJVMLegacy.class.getName();
|
||||
SafeExitJVM.class.getName();
|
||||
NativeJVMHalt.class.getName();
|
||||
NativeJVMHalt.initFunc();
|
||||
isAgentStarted = true;
|
||||
boolean pb = true;
|
||||
boolean rt = true;
|
||||
if (agentArgument != null) {
|
||||
String trimmedArg = agentArgument.trim();
|
||||
if (!trimmedArg.isEmpty()) {
|
||||
if (trimmedArg.contains("p")) pb = false;
|
||||
if (trimmedArg.contains("r")) rt = false;
|
||||
}
|
||||
String trimmedArg = agentArgument.trim();
|
||||
if (!trimmedArg.isEmpty()) {
|
||||
if (trimmedArg.contains("p")) pb = false;
|
||||
if (trimmedArg.contains("r")) rt = false;
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (ManagementFactory.getOperatingSystemMXBean().getName().startsWith("Windows")) replaceClasses(pb, rt);
|
||||
else replaceClasses(false, false);
|
||||
if (ManagementFactory.getOperatingSystemMXBean().getName().startsWith("Windows")) replaceClasses(pb, rt);
|
||||
else replaceClasses(false, false);
|
||||
} catch (Error e) {
|
||||
NativeJVMHalt.haltA(294);
|
||||
throw e;
|
||||
NativeJVMHalt.haltA(294);
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -67,109 +67,112 @@ public static boolean isStarted() {
|
|||
}
|
||||
|
||||
private static void replaceClasses(boolean pb, boolean rt) {
|
||||
java.awt.Robot.class.getName();
|
||||
List<java.lang.instrument.ClassDefinition> defs = new ArrayList<>();
|
||||
if(rt) {
|
||||
try {
|
||||
defs.add(new java.lang.instrument.ClassDefinition(java.lang.Runtime.class, transformClass(java.lang.Runtime.class.getName(), getClassFile(java.lang.Runtime.class))));
|
||||
} catch(Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
if(pb) {
|
||||
try {
|
||||
defs.add(new java.lang.instrument.ClassDefinition(java.lang.ProcessBuilder.class, transformClass(java.lang.ProcessBuilder.class.getName(), getClassFile(java.lang.ProcessBuilder.class))));
|
||||
} catch(Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
defs.add(new java.lang.instrument.ClassDefinition(java.awt.Robot.class, transformClass(java.awt.Robot.class.getName(), getClassFile(java.awt.Robot.class))));
|
||||
} catch(Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
try {
|
||||
inst.redefineClasses(defs.toArray(new java.lang.instrument.ClassDefinition[0]));
|
||||
} catch(Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
java.awt.Robot.class.getName();
|
||||
List<java.lang.instrument.ClassDefinition> defs = new ArrayList<>();
|
||||
if (rt) {
|
||||
try {
|
||||
defs.add(new java.lang.instrument.ClassDefinition(java.lang.Runtime.class, transformClass(java.lang.Runtime.class.getName(), getClassFile(java.lang.Runtime.class))));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
if (pb) {
|
||||
try {
|
||||
defs.add(new java.lang.instrument.ClassDefinition(java.lang.ProcessBuilder.class, transformClass(java.lang.ProcessBuilder.class.getName(), getClassFile(java.lang.ProcessBuilder.class))));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
defs.add(new java.lang.instrument.ClassDefinition(java.awt.Robot.class, transformClass(java.awt.Robot.class.getName(), getClassFile(java.awt.Robot.class))));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
try {
|
||||
inst.redefineClasses(defs.toArray(new java.lang.instrument.ClassDefinition[0]));
|
||||
} catch (Exception e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @author https://github.com/Konloch/JVM-Sandbox
|
||||
* Use ASM to modify the byte array
|
||||
*/
|
||||
private static byte[] transformClass(String className, byte[] classBytes) {
|
||||
if (className.equals("java.lang.Runtime")) {
|
||||
ClassReader cr=new ClassReader(classBytes);
|
||||
ClassNode cn=new ClassNode();
|
||||
cr.accept(cn,ClassReader.EXPAND_FRAMES);
|
||||
|
||||
for (Object o : cn.methods.toArray()) {
|
||||
MethodNode m = (MethodNode) o;
|
||||
if(m.name.equals("exec")) {
|
||||
m.instructions.insert(new InsnNode(ARETURN));
|
||||
m.instructions.insert(new InsnNode(ACONST_NULL));
|
||||
}
|
||||
}
|
||||
ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
return cw.toByteArray();
|
||||
} else if (className.equals("java.lang.ProcessBuilder")) {
|
||||
ClassReader cr=new ClassReader(classBytes);
|
||||
ClassNode cn=new ClassNode();
|
||||
cr.accept(cn,ClassReader.EXPAND_FRAMES);
|
||||
|
||||
for (Object o : cn.methods.toArray()) {
|
||||
MethodNode m = (MethodNode) o;
|
||||
if(m.name.equals("start")) {
|
||||
m.instructions.insert(new InsnNode(ARETURN));
|
||||
m.instructions.insert(new InsnNode(ACONST_NULL));
|
||||
}
|
||||
}
|
||||
ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
return cw.toByteArray();
|
||||
} else if (className.equals("java.awt.Robot")) {
|
||||
ClassReader cr=new ClassReader(classBytes);
|
||||
ClassNode cn=new ClassNode();
|
||||
cr.accept(cn,ClassReader.EXPAND_FRAMES);
|
||||
|
||||
for (Object o : cn.methods.toArray()) {
|
||||
MethodNode m = (MethodNode) o;
|
||||
if( m.name.equals("createScreenCapture") || m.name.equals("getPixelColor") ||
|
||||
m.name.equals("keyPress") || m.name.equals("keyRelease") ||
|
||||
m.name.equals("mouseMove") || m.name.equals("mousePress") ||
|
||||
m.name.equals("mouseWheel"))
|
||||
{
|
||||
m.instructions.insert(new InsnNode(ARETURN));
|
||||
m.instructions.insert(new InsnNode(ACONST_NULL));
|
||||
}
|
||||
}
|
||||
ClassWriter cw=new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
return cw.toByteArray();
|
||||
}
|
||||
return classBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Use ASM to modify the byte array
|
||||
*/
|
||||
private static byte[] transformClass(String className, byte[] classBytes) {
|
||||
switch (className) {
|
||||
case "java.lang.Runtime": {
|
||||
ClassReader cr = new ClassReader(classBytes);
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, ClassReader.EXPAND_FRAMES);
|
||||
|
||||
for (Object o : cn.methods.toArray()) {
|
||||
MethodNode m = (MethodNode) o;
|
||||
if (m.name.equals("exec")) {
|
||||
m.instructions.insert(new InsnNode(ARETURN));
|
||||
m.instructions.insert(new InsnNode(ACONST_NULL));
|
||||
}
|
||||
}
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
return cw.toByteArray();
|
||||
}
|
||||
case "java.lang.ProcessBuilder": {
|
||||
ClassReader cr = new ClassReader(classBytes);
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, ClassReader.EXPAND_FRAMES);
|
||||
|
||||
for (Object o : cn.methods.toArray()) {
|
||||
MethodNode m = (MethodNode) o;
|
||||
if (m.name.equals("start")) {
|
||||
m.instructions.insert(new InsnNode(ARETURN));
|
||||
m.instructions.insert(new InsnNode(ACONST_NULL));
|
||||
}
|
||||
}
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
return cw.toByteArray();
|
||||
}
|
||||
case "java.awt.Robot": {
|
||||
ClassReader cr = new ClassReader(classBytes);
|
||||
ClassNode cn = new ClassNode();
|
||||
cr.accept(cn, ClassReader.EXPAND_FRAMES);
|
||||
|
||||
for (Object o : cn.methods.toArray()) {
|
||||
MethodNode m = (MethodNode) o;
|
||||
if (m.name.equals("createScreenCapture") || m.name.equals("getPixelColor") ||
|
||||
m.name.equals("keyPress") || m.name.equals("keyRelease") ||
|
||||
m.name.equals("mouseMove") || m.name.equals("mousePress") ||
|
||||
m.name.equals("mouseWheel")) {
|
||||
m.instructions.insert(new InsnNode(ARETURN));
|
||||
m.instructions.insert(new InsnNode(ACONST_NULL));
|
||||
}
|
||||
}
|
||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_FRAMES | ClassWriter.COMPUTE_MAXS);
|
||||
cn.accept(cw);
|
||||
return cw.toByteArray();
|
||||
}
|
||||
}
|
||||
return classBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clazz
|
||||
* @return array, respending this class in bytecode.
|
||||
* @throws IOException
|
||||
* @author https://github.com/Konloch/JVM-Sandbox
|
||||
* Do not remove this method. Do not to cause classloading!
|
||||
* Grab the byte array from the loaded Class object
|
||||
* @param clazz
|
||||
* @return array, respending this class in bytecode.
|
||||
* @throws IOException
|
||||
*/
|
||||
private static byte[] getClassFile(Class<?> clazz) throws IOException {
|
||||
try (InputStream is = clazz.getResourceAsStream( "/" + clazz.getName().replace('.', '/') + ".class");
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
int r = 0;
|
||||
byte[] buffer = new byte[8192];
|
||||
while((r=is.read(buffer))>=0) {
|
||||
baos.write(buffer, 0, r);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
}
|
||||
* Grab the byte array from the loaded Class object
|
||||
*/
|
||||
private static byte[] getClassFile(Class<?> clazz) throws IOException {
|
||||
try (InputStream is = clazz.getResourceAsStream("/" + clazz.getName().replace('.', '/') + ".class");
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
|
||||
int r = 0;
|
||||
byte[] buffer = new byte[8192];
|
||||
while ((r = is.read(buffer)) >= 0) {
|
||||
baos.write(buffer, 0, r);
|
||||
}
|
||||
return baos.toByteArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,9 +33,8 @@ public static void main(String... args) throws Throwable {
|
|||
initGson();
|
||||
ConsoleManager.initConsole();
|
||||
LauncherConfig config = Launcher.getConfig();
|
||||
if(config.environment.equals(LauncherConfig.LauncherEnvironment.PROD))
|
||||
{
|
||||
if(!LauncherAgent.isStarted()) throw new SecurityException("LauncherAgent must started");
|
||||
if (config.environment.equals(LauncherConfig.LauncherEnvironment.PROD)) {
|
||||
if (!LauncherAgent.isStarted()) throw new SecurityException("LauncherAgent must started");
|
||||
}
|
||||
long startTime = System.currentTimeMillis();
|
||||
try {
|
||||
|
@ -73,8 +72,7 @@ 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);
|
||||
|
|
|
@ -11,6 +11,8 @@ public class NewLauncherSettings {
|
|||
@LauncherAPI
|
||||
public String login;
|
||||
@LauncherAPI
|
||||
public String auth;
|
||||
@LauncherAPI
|
||||
public byte[] rsaPassword;
|
||||
@LauncherAPI
|
||||
public int profile;
|
||||
|
@ -35,8 +37,8 @@ public class NewLauncherSettings {
|
|||
public List<ClientProfile> lastProfiles = new LinkedList<>();
|
||||
@LauncherAPI
|
||||
public Map<String, UserSettings> userSettings = new HashMap<>();
|
||||
public static class HashedStoreEntry
|
||||
{
|
||||
|
||||
public static class HashedStoreEntry {
|
||||
@LauncherAPI
|
||||
public HashedDir hdir;
|
||||
@LauncherAPI
|
||||
|
@ -50,15 +52,15 @@ public HashedStoreEntry(HashedDir hdir, String name, String fullPath) {
|
|||
this.fullPath = fullPath;
|
||||
}
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public transient List<HashedStoreEntry> lastHDirs = new ArrayList<>(16);
|
||||
|
||||
@LauncherAPI
|
||||
public void putHDir(String name, Path path, HashedDir dir)
|
||||
{
|
||||
public void putHDir(String name, Path path, HashedDir dir) {
|
||||
String fullPath = path.toAbsolutePath().toString();
|
||||
for(HashedStoreEntry e : lastHDirs)
|
||||
{
|
||||
if(e.fullPath.equals(fullPath) && e.name.equals(name)) return;
|
||||
for (HashedStoreEntry e : lastHDirs) {
|
||||
if (e.fullPath.equals(fullPath) && e.name.equals(name)) return;
|
||||
}
|
||||
lastHDirs.add(new HashedStoreEntry(dir, name, fullPath));
|
||||
}
|
||||
|
|
|
@ -541,8 +541,7 @@ 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);
|
||||
HashedDir.Diff diff = hdir.diff(currentHDir, matcher);
|
||||
if (!diff.isSame())
|
||||
{
|
||||
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); }
|
||||
|
|
|
@ -68,19 +68,19 @@ public static Path getAppDataDir() throws IOException {
|
|||
public static Path getLauncherDir(String projectname) throws IOException {
|
||||
return getAppDataDir().resolve(projectname);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static Path getStoreDir(String projectname) throws IOException
|
||||
{
|
||||
if(JVMHelper.OS_TYPE == JVMHelper.OS.LINUX)
|
||||
public static Path getStoreDir(String projectname) throws IOException {
|
||||
if (JVMHelper.OS_TYPE == JVMHelper.OS.LINUX)
|
||||
return getAppDataDir().resolve("store");
|
||||
else if(JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE)
|
||||
else if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE)
|
||||
return getAppDataDir().resolve("GravitLauncherStore");
|
||||
else
|
||||
return getAppDataDir().resolve("minecraftStore");
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static Path getProjectStoreDir(String projectname) throws IOException
|
||||
{
|
||||
public static Path getProjectStoreDir(String projectname) throws IOException {
|
||||
return getStoreDir(projectname).resolve(projectname);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ public class FunctionalBridge {
|
|||
public static AtomicReference<HWID> hwid = new AtomicReference<>();
|
||||
@LauncherAPI
|
||||
public static Thread getHWID = null;
|
||||
|
||||
|
||||
private static long cachedMemorySize = -1;
|
||||
|
||||
@LauncherAPI
|
||||
|
@ -57,8 +57,8 @@ public static HWID getHWID() {
|
|||
|
||||
@LauncherAPI
|
||||
public static int getTotalMemory() {
|
||||
if (cachedMemorySize > 0) return (int)cachedMemorySize;
|
||||
return (int)(cachedMemorySize = hwidProvider.getTotalMemory() >> 20);
|
||||
if (cachedMemorySize > 0) return (int) cachedMemorySize;
|
||||
return (int) (cachedMemorySize = hwidProvider.getTotalMemory() >> 20);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
|
@ -79,21 +79,20 @@ public static int getJVMTotalMemory() {
|
|||
public static HasherStore getDefaultHasherStore() {
|
||||
return HasherManager.getDefaultStore();
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void registerUserSettings(String typename, Class<? extends UserSettings> clazz)
|
||||
{
|
||||
public static void registerUserSettings(String typename, Class<? extends UserSettings> clazz) {
|
||||
UserSettings.providers.register(typename, clazz);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void close() throws Exception
|
||||
{
|
||||
public static void close() throws Exception {
|
||||
threadPool.awaitTermination(2, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void setAuthParams(AuthRequestEvent event) {
|
||||
if(event.session != 0)
|
||||
{
|
||||
if (event.session != 0) {
|
||||
Request.setSession(event.session);
|
||||
}
|
||||
LauncherGuardManager.guard.setProtectToken(event.protectToken);
|
||||
|
@ -105,13 +104,12 @@ public interface HashedDirRunnable {
|
|||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void evalCommand(String cmd)
|
||||
{
|
||||
public static void evalCommand(String cmd) {
|
||||
ConsoleManager.handler.eval(cmd, false);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static void addPlainOutput(LogHelper.Output output)
|
||||
{
|
||||
public static void addPlainOutput(LogHelper.Output output) {
|
||||
LogHelper.addOutput(output, LogHelper.OutputTypes.PLAIN);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,14 +18,11 @@ public String getUsageDescription() {
|
|||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
verifyArgs(args, 1);
|
||||
if(ConsoleManager.checkUnlockKey(args[0]))
|
||||
{
|
||||
if (ConsoleManager.checkUnlockKey(args[0])) {
|
||||
LogHelper.info("Unlock successful");
|
||||
ConsoleManager.unlock();
|
||||
ConsoleManager.handler.unregisterCommand("unlock");
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
LogHelper.error("Unlock key incorrect");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,6 @@ public String getUsageDescription() {
|
|||
@Override
|
||||
public void invoke(String... args) throws Exception {
|
||||
ExecCommandRequestEvent request = new ExecCommandRequest(String.join(" ", args)).request();
|
||||
if(!request.success) LogHelper.error("Error executing command");
|
||||
if (!request.success) LogHelper.error("Error executing command");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,7 @@
|
|||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public class LogListenerCommand extends Command {
|
||||
public class LogListenerRequest implements RequestInterface
|
||||
{
|
||||
public class LogListenerRequest implements RequestInterface {
|
||||
@LauncherNetworkAPI
|
||||
public LogHelper.OutputTypes outputType;
|
||||
|
||||
|
@ -22,6 +21,7 @@ public String getType() {
|
|||
return "addLogListener";
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getArgsDescription() {
|
||||
return null;
|
||||
|
@ -38,15 +38,8 @@ public void invoke(String... args) throws Exception {
|
|||
Request.service.sendObject(new LogListenerRequest(LogHelper.JANSI ? LogHelper.OutputTypes.JANSI : LogHelper.OutputTypes.PLAIN));
|
||||
LogHelper.info("Add log handler");
|
||||
Request.service.registerHandler((result) -> {
|
||||
if(result instanceof LogEvent)
|
||||
{
|
||||
LogHelper.rawLog(() -> {
|
||||
return ((LogEvent) result).string;
|
||||
}, () -> {
|
||||
return ((LogEvent) result).string;
|
||||
}, () -> {
|
||||
return ((LogEvent) result).string;
|
||||
});
|
||||
if (result instanceof LogEvent) {
|
||||
LogHelper.rawLog(() -> ((LogEvent) result).string, () -> ((LogEvent) result).string, () -> ((LogEvent) result).string);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -10,20 +10,16 @@ public class LauncherGuardManager {
|
|||
|
||||
public static void initGuard(boolean clientInstance) {
|
||||
LauncherConfig config = Launcher.getConfig();
|
||||
switch (config.guardType)
|
||||
{
|
||||
case "wrapper":
|
||||
{
|
||||
switch (config.guardType) {
|
||||
case "wrapper": {
|
||||
guard = new LauncherWrapperGuard();
|
||||
break;
|
||||
break;
|
||||
}
|
||||
case "java":
|
||||
{
|
||||
case "java": {
|
||||
guard = new LauncherJavaGuard();
|
||||
break;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
default: {
|
||||
guard = new LauncherNoGuard();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ public String getMacAddr() {
|
|||
}
|
||||
|
||||
public long getTotalMemory() {
|
||||
if (noHWID) return 1024<<20;
|
||||
if (noHWID) return 1024 << 20;
|
||||
if (hardware == null) hardware = systemInfo.getHardware();
|
||||
return hardware.getMemory().getTotal();
|
||||
}
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
package ru.gravit.launcher.managers;
|
||||
|
||||
import ru.gravit.launcher.console.UnlockCommand;
|
||||
import ru.gravit.launcher.console.admin.ExecCommand;
|
||||
import ru.gravit.launcher.console.admin.LogListenerCommand;
|
||||
import ru.gravit.utils.command.BaseCommandCategory;
|
||||
import ru.gravit.utils.command.basic.ClearCommand;
|
||||
import ru.gravit.utils.command.basic.DebugCommand;
|
||||
import ru.gravit.utils.command.basic.GCCommand;
|
||||
import ru.gravit.launcher.console.UnlockCommand;
|
||||
import ru.gravit.utils.command.CommandHandler;
|
||||
import ru.gravit.utils.command.JLineCommandHandler;
|
||||
import ru.gravit.utils.command.StdCommandHandler;
|
||||
import ru.gravit.utils.command.basic.ClearCommand;
|
||||
import ru.gravit.utils.command.basic.DebugCommand;
|
||||
import ru.gravit.utils.command.basic.GCCommand;
|
||||
import ru.gravit.utils.command.basic.HelpCommand;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
@ -19,11 +19,11 @@
|
|||
public class ConsoleManager {
|
||||
public static CommandHandler handler;
|
||||
public static Thread thread;
|
||||
public static void initConsole() throws IOException
|
||||
{
|
||||
|
||||
public static void initConsole() throws IOException {
|
||||
CommandHandler localCommandHandler;
|
||||
try {
|
||||
Class.forName("jline.Terminal");
|
||||
Class.forName("org.jline.terminal.Terminal");
|
||||
|
||||
// JLine2 available
|
||||
localCommandHandler = new JLineCommandHandler();
|
||||
|
@ -37,19 +37,19 @@ public static void initConsole() throws IOException
|
|||
thread = CommonHelper.newThread("Launcher Console", true, handler);
|
||||
thread.start();
|
||||
}
|
||||
public static void registerCommands()
|
||||
{
|
||||
|
||||
public static void registerCommands() {
|
||||
handler.registerCommand("help", new HelpCommand(handler));
|
||||
handler.registerCommand("gc", new GCCommand());
|
||||
handler.registerCommand("clear", new ClearCommand(handler));
|
||||
handler.registerCommand("unlock", new UnlockCommand());
|
||||
}
|
||||
public static boolean checkUnlockKey(String key)
|
||||
{
|
||||
|
||||
public static boolean checkUnlockKey(String key) {
|
||||
return true;
|
||||
}
|
||||
public static void unlock()
|
||||
{
|
||||
|
||||
public static void unlock() {
|
||||
handler.registerCommand("debug", new DebugCommand());
|
||||
BaseCommandCategory admin = new BaseCommandCategory();
|
||||
admin.registerCommand("exec", new ExecCommand());
|
||||
|
|
|
@ -3,10 +3,10 @@
|
|||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.NewLauncherSettings;
|
||||
import ru.gravit.launcher.client.DirBridge;
|
||||
import ru.gravit.launcher.config.JsonConfigurable;
|
||||
import ru.gravit.launcher.hasher.HashedDir;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.config.JsonConfigurable;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -18,10 +18,8 @@ public class SettingsManager extends JsonConfigurable<NewLauncherSettings> {
|
|||
public class StoreFileVisitor extends SimpleFileVisitor<Path> {
|
||||
@Override
|
||||
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
||||
throws IOException
|
||||
{
|
||||
try(HInput input = new HInput(IOHelper.newInput(file)))
|
||||
{
|
||||
throws IOException {
|
||||
try (HInput input = new HInput(IOHelper.newInput(file))) {
|
||||
String dirName = input.readString(128);
|
||||
String fullPath = input.readString(1024);
|
||||
HashedDir dir = new HashedDir(input);
|
||||
|
@ -31,61 +29,63 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs)
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public static NewLauncherSettings settings;
|
||||
|
||||
public SettingsManager() {
|
||||
super(NewLauncherSettings.class, DirBridge.dir.resolve("settings.json"));
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
@Override
|
||||
public NewLauncherSettings getConfig() {
|
||||
if(settings.updatesDir != null)
|
||||
settings.updatesDirPath = settings.updatesDir.toString();
|
||||
if (settings.updatesDir != null)
|
||||
settings.updatesDirPath = settings.updatesDir.toString();
|
||||
return settings;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
@Override
|
||||
public NewLauncherSettings getDefaultConfig() {
|
||||
return new NewLauncherSettings();
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
@Override
|
||||
public void setConfig(NewLauncherSettings config) {
|
||||
settings = config;
|
||||
if(settings.updatesDirPath != null)
|
||||
settings.updatesDir = Paths.get(settings.updatesDirPath);
|
||||
if (settings.updatesDirPath != null)
|
||||
settings.updatesDir = Paths.get(settings.updatesDirPath);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void loadHDirStore(Path storePath) throws IOException
|
||||
{
|
||||
public void loadHDirStore(Path storePath) throws IOException {
|
||||
Files.createDirectories(storePath);
|
||||
IOHelper.walk(storePath, new StoreFileVisitor(), false);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void saveHDirStore(Path storeProjectPath) throws IOException
|
||||
{
|
||||
public void saveHDirStore(Path storeProjectPath) throws IOException {
|
||||
Files.createDirectories(storeProjectPath);
|
||||
for(NewLauncherSettings.HashedStoreEntry e : settings.lastHDirs)
|
||||
{
|
||||
for (NewLauncherSettings.HashedStoreEntry e : settings.lastHDirs) {
|
||||
Path file = storeProjectPath.resolve(e.name.concat(".bin"));
|
||||
if(!Files.exists(file)) Files.createFile(file);
|
||||
try(HOutput output = new HOutput(IOHelper.newOutput(file)))
|
||||
{
|
||||
if (!Files.exists(file)) Files.createFile(file);
|
||||
try (HOutput output = new HOutput(IOHelper.newOutput(file))) {
|
||||
output.writeString(e.name, 128);
|
||||
output.writeString(e.fullPath, 1024);
|
||||
e.hdir.write(output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void loadHDirStore() throws IOException
|
||||
{
|
||||
public void loadHDirStore() throws IOException {
|
||||
loadHDirStore(DirBridge.dirStore);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void saveHDirStore() throws IOException
|
||||
{
|
||||
public void saveHDirStore() throws IOException {
|
||||
saveHDirStore(DirBridge.dirProjectStore);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
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.HashedFile;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.JVMHelper;
|
||||
import ru.gravit.utils.helper.JVMHelper.OS;
|
||||
|
|
|
@ -14,26 +14,26 @@ public NativeJVMHalt(int haltCode) {
|
|||
public native void aaabbb38C_D();
|
||||
|
||||
@SuppressWarnings("null")
|
||||
private boolean aaabBooleanC_D() {
|
||||
return (boolean) (Boolean) (Object) null;
|
||||
private boolean aaabBooleanC_D() {
|
||||
return (boolean) (Boolean) null;
|
||||
}
|
||||
|
||||
|
||||
public static void haltA(int code) {
|
||||
NativeJVMHalt halt = new NativeJVMHalt(code);
|
||||
try {
|
||||
SafeExitJVMLegacy.exit(code);
|
||||
} catch(Throwable ignored) {
|
||||
}
|
||||
SafeExitJVMLegacy.exit(code);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
try {
|
||||
SafeExitJVM.exit(code);
|
||||
} catch(Throwable ignored) {
|
||||
}
|
||||
halt.aaabbb38C_D();
|
||||
SafeExitJVM.exit(code);
|
||||
} catch (Throwable ignored) {
|
||||
}
|
||||
halt.aaabbb38C_D();
|
||||
boolean a = halt.aaabBooleanC_D();
|
||||
System.out.println(Boolean.toString(a));
|
||||
System.out.println(a);
|
||||
}
|
||||
|
||||
|
||||
public static boolean initFunc() {
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,25 +13,30 @@
|
|||
public abstract class JsonConfigurable<T> {
|
||||
private Type type;
|
||||
protected Path configPath;
|
||||
|
||||
@LauncherAPI
|
||||
public void saveConfig() throws IOException {
|
||||
saveConfig(configPath);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void loadConfig() throws IOException {
|
||||
loadConfig(configPath);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public JsonConfigurable(Type type, Path configPath) {
|
||||
this.type = type;
|
||||
this.configPath = configPath;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void saveConfig(Path configPath) throws IOException {
|
||||
try (BufferedWriter writer = IOHelper.newWriter(configPath)) {
|
||||
Launcher.gsonManager.gson.toJson(getConfig(), type, writer);
|
||||
}
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void loadConfig(Path configPath) throws IOException {
|
||||
if (generateConfigIfNotExists(configPath)) return;
|
||||
|
@ -39,16 +44,19 @@ public void loadConfig(Path configPath) throws IOException {
|
|||
setConfig(Launcher.gsonManager.gson.fromJson(reader, type));
|
||||
}
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void resetConfig() throws IOException {
|
||||
setConfig(getDefaultConfig());
|
||||
saveConfig();
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void resetConfig(Path newPath) throws IOException {
|
||||
setConfig(getDefaultConfig());
|
||||
saveConfig(newPath);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public boolean generateConfigIfNotExists(Path path) throws IOException {
|
||||
if (IOHelper.isFile(path))
|
||||
|
@ -56,6 +64,7 @@ public boolean generateConfigIfNotExists(Path path) throws IOException {
|
|||
resetConfig(path);
|
||||
return true;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public boolean generateConfigIfNotExists() throws IOException {
|
||||
if (IOHelper.isFile(configPath))
|
||||
|
@ -63,14 +72,17 @@ public boolean generateConfigIfNotExists() throws IOException {
|
|||
resetConfig();
|
||||
return true;
|
||||
}
|
||||
protected void setType(Type type)
|
||||
{
|
||||
|
||||
protected void setType(Type type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public abstract T getConfig();
|
||||
|
||||
@LauncherAPI
|
||||
public abstract T getDefaultConfig();
|
||||
|
||||
@LauncherAPI
|
||||
public abstract void setConfig(T config);
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package ru.gravit.launcher.downloader;
|
||||
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.ResponseHandler;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.impl.client.CloseableHttpClient;
|
||||
|
@ -19,20 +18,21 @@
|
|||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.util.List;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
public class ListDownloader {
|
||||
@FunctionalInterface
|
||||
public interface DownloadCallback
|
||||
{
|
||||
void stateChanged(String filename,long downloadedSize, long size);
|
||||
public interface DownloadCallback {
|
||||
void stateChanged(String filename, long downloadedSize, long size);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface DownloadTotalCallback
|
||||
{
|
||||
public interface DownloadTotalCallback {
|
||||
void addTotal(long size);
|
||||
}
|
||||
public static class DownloadTask
|
||||
{
|
||||
|
||||
public static class DownloadTask {
|
||||
public String apply;
|
||||
public long size;
|
||||
|
||||
|
@ -41,6 +41,7 @@ public DownloadTask(String apply, long size) {
|
|||
this.size = size;
|
||||
}
|
||||
}
|
||||
|
||||
public void download(String base, List<DownloadTask> applies, Path dstDirFile, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException, URISyntaxException {
|
||||
try (CloseableHttpClient httpclient = HttpClients.custom()
|
||||
.setRedirectStrategy(new LaxRedirectStrategy())
|
||||
|
@ -49,20 +50,30 @@ public void download(String base, List<DownloadTask> applies, Path dstDirFile, D
|
|||
HttpGet get = null;
|
||||
for (DownloadTask apply : applies) {
|
||||
URI u = new URL(base.concat(IOHelper.urlEncode(apply.apply).replace("%2F", "/"))).toURI();
|
||||
callback.stateChanged(apply.apply,0L, apply.size);
|
||||
callback.stateChanged(apply.apply, 0L, apply.size);
|
||||
LogHelper.debug("Download URL: %s", u.toString());
|
||||
if (get == null) get = new HttpGet(u);
|
||||
else {
|
||||
get.reset();
|
||||
get.setURI(u);
|
||||
}
|
||||
httpclient.execute(get, new FileDownloadResponseHandler(dstDirFile.resolve(apply.apply), apply, callback, totalCallback));
|
||||
httpclient.execute(get, new FileDownloadResponseHandler(dstDirFile.resolve(apply.apply), apply, callback, totalCallback, false));
|
||||
}
|
||||
}
|
||||
}
|
||||
public void downloadZip(String base, Path dstDirFile, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException, URISyntaxException {
|
||||
try (CloseableHttpClient httpclient = HttpClients.custom()
|
||||
.setRedirectStrategy(new LaxRedirectStrategy())
|
||||
.build()) {
|
||||
HttpGet get;
|
||||
URI u = new URL(base).toURI();
|
||||
LogHelper.debug("Download ZIP URL: %s", u.toString());
|
||||
get = new HttpGet(u);
|
||||
httpclient.execute(get, new FileDownloadResponseHandler(dstDirFile, callback, totalCallback, true));
|
||||
}
|
||||
}
|
||||
|
||||
public void downloadOne(String url, Path target) throws IOException, URISyntaxException
|
||||
{
|
||||
public void downloadOne(String url, Path target) throws IOException, URISyntaxException {
|
||||
try (CloseableHttpClient httpclient = HttpClients.custom()
|
||||
.setRedirectStrategy(new LaxRedirectStrategy())
|
||||
.build()) {
|
||||
|
@ -80,36 +91,58 @@ static class FileDownloadResponseHandler implements ResponseHandler<Path> {
|
|||
private final DownloadTask task;
|
||||
private final DownloadCallback callback;
|
||||
private final DownloadTotalCallback totalCallback;
|
||||
private final boolean zip;
|
||||
|
||||
public FileDownloadResponseHandler(Path target) {
|
||||
this.target = target;
|
||||
this.task = null;
|
||||
this.zip = false;
|
||||
callback = null;
|
||||
totalCallback = null;
|
||||
}
|
||||
|
||||
public FileDownloadResponseHandler(Path target, DownloadTask task, DownloadCallback callback, DownloadTotalCallback totalCallback) {
|
||||
public FileDownloadResponseHandler(Path target, DownloadTask task, DownloadCallback callback, DownloadTotalCallback totalCallback, boolean zip) {
|
||||
this.target = target;
|
||||
this.task = task;
|
||||
this.callback = callback;
|
||||
this.totalCallback = totalCallback;
|
||||
this.zip = zip;
|
||||
}
|
||||
|
||||
public FileDownloadResponseHandler(Path target, DownloadCallback callback, DownloadTotalCallback totalCallback, boolean zip) {
|
||||
this.target = target;
|
||||
this.task = null;
|
||||
this.callback = callback;
|
||||
this.totalCallback = totalCallback;
|
||||
this.zip = zip;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Path handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
|
||||
public Path handleResponse(HttpResponse response) throws IOException {
|
||||
InputStream source = response.getEntity().getContent();
|
||||
if(callback != null && task != null)
|
||||
if(zip)
|
||||
{
|
||||
try(ZipInputStream input = IOHelper.newZipInput(source))
|
||||
{
|
||||
ZipEntry entry = input.getNextEntry();
|
||||
long size = entry.getSize();
|
||||
String filename = entry.getName();
|
||||
Path target = this.target.resolve(filename);
|
||||
LogHelper.dev("Resolved filename %s to %s", filename, target.toAbsolutePath().toString());
|
||||
transfer(source, target, filename, size, callback, totalCallback);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
if (callback != null && task != null) {
|
||||
callback.stateChanged(task.apply, 0, task.size);
|
||||
transfer(source, this.target, task.apply, task.size, callback, totalCallback);
|
||||
}
|
||||
else
|
||||
} else
|
||||
IOHelper.transfer(source, this.target);
|
||||
return this.target;
|
||||
}
|
||||
}
|
||||
public static void transfer(InputStream input, Path file, String filename, long size, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException
|
||||
{
|
||||
|
||||
public static void transfer(InputStream input, Path file, String filename, long size, DownloadCallback callback, DownloadTotalCallback totalCallback) throws IOException {
|
||||
try (OutputStream fileOutput = IOHelper.newOutput(file)) {
|
||||
long downloaded = 0L;
|
||||
|
||||
|
|
|
@ -12,6 +12,7 @@ public class ErrorRequestEvent extends RequestEvent implements EventInterface {
|
|||
public ErrorRequestEvent(String error) {
|
||||
this.error = error;
|
||||
}
|
||||
|
||||
@LauncherNetworkAPI
|
||||
public final String error;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ public class ExecCommandRequestEvent extends RequestEvent {
|
|||
public String getType() {
|
||||
return "cmdExec";
|
||||
}
|
||||
|
||||
@LauncherNetworkAPI
|
||||
public boolean success;
|
||||
|
||||
|
|
|
@ -6,8 +6,7 @@
|
|||
import java.util.List;
|
||||
|
||||
public class GetAvailabilityAuthRequestEvent extends RequestEvent {
|
||||
public static class AuthAvailability
|
||||
{
|
||||
public static class AuthAvailability {
|
||||
@LauncherNetworkAPI
|
||||
public String name;
|
||||
@LauncherNetworkAPI
|
||||
|
@ -18,6 +17,7 @@ public AuthAvailability(String name, String displayName) {
|
|||
this.displayName = displayName;
|
||||
}
|
||||
}
|
||||
|
||||
@LauncherNetworkAPI
|
||||
public List<AuthAvailability> list;
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
public class GetSecureTokenRequestEvent extends RequestEvent {
|
||||
@LauncherNetworkAPI
|
||||
public String secureToken;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "GetSecureToken";
|
||||
|
|
|
@ -12,6 +12,7 @@ public class JoinServerRequestEvent extends RequestEvent implements EventInterfa
|
|||
public JoinServerRequestEvent(boolean allow) {
|
||||
this.allow = allow;
|
||||
}
|
||||
|
||||
@LauncherNetworkAPI
|
||||
public boolean allow;
|
||||
|
||||
|
|
|
@ -19,6 +19,7 @@ public LauncherRequestEvent(boolean needUpdate, String url) {
|
|||
this.needUpdate = needUpdate;
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
@LauncherNetworkAPI
|
||||
public boolean needUpdate;
|
||||
|
||||
|
|
|
@ -8,6 +8,7 @@ public class LogEvent implements ResultInterface {
|
|||
public String getType() {
|
||||
return "log";
|
||||
}
|
||||
|
||||
@LauncherNetworkAPI
|
||||
public String string;
|
||||
|
||||
|
|
|
@ -9,6 +9,8 @@ public class UpdateRequestEvent extends RequestEvent {
|
|||
public HashedDir hdir;
|
||||
@LauncherNetworkAPI
|
||||
public String url;
|
||||
@LauncherNetworkAPI
|
||||
public boolean zip;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
|
@ -17,10 +19,18 @@ public String getType() {
|
|||
|
||||
public UpdateRequestEvent(HashedDir hdir) {
|
||||
this.hdir = hdir;
|
||||
this.zip = false;
|
||||
}
|
||||
|
||||
public UpdateRequestEvent(HashedDir hdir, String url) {
|
||||
this.hdir = hdir;
|
||||
this.url = url;
|
||||
this.zip = false;
|
||||
}
|
||||
|
||||
public UpdateRequestEvent(HashedDir hdir, String url, boolean zip) {
|
||||
this.hdir = hdir;
|
||||
this.url = url;
|
||||
this.zip = zip;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
public class VerifySecureTokenRequestEvent extends RequestEvent {
|
||||
@LauncherAPI
|
||||
public boolean success;
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "verifySecureToken";
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public class ConfigManager {
|
||||
private final HashMap<String, JsonConfigurable> CONFIGURABLE = new HashMap<>();
|
||||
private final HashMap<String, JsonConfigurable> CONFIGURABLE = new HashMap<>();
|
||||
|
||||
public void registerConfigurable(String name, JsonConfigurable reconfigurable) {
|
||||
VerifyHelper.putIfAbsent(CONFIGURABLE, name.toLowerCase(), Objects.requireNonNull(reconfigurable, "adapter"),
|
||||
|
|
|
@ -259,7 +259,7 @@ public void unmarkOptional(OptionalFile file) {
|
|||
file.mark = false;
|
||||
if (file.dependenciesCount != null) {
|
||||
for (OptionalFile f : file.dependenciesCount) {
|
||||
if(f.isPreset) continue;
|
||||
if (f.isPreset) continue;
|
||||
unmarkOptional(f);
|
||||
}
|
||||
file.dependenciesCount.clear();
|
||||
|
|
|
@ -35,9 +35,11 @@ public static void requestError(String message) throws RequestException {
|
|||
public R request() throws Exception {
|
||||
if (!started.compareAndSet(false, true))
|
||||
throw new IllegalStateException("Request already started");
|
||||
if(service == null) service = StandartClientWebSocketService.initWebSockets(Launcher.getConfig().address, false);
|
||||
if (service == null)
|
||||
service = StandartClientWebSocketService.initWebSockets(Launcher.getConfig().address, false);
|
||||
return requestDo(service);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public R request(StandartClientWebSocketService service) throws Exception {
|
||||
if (!started.compareAndSet(false, true))
|
||||
|
@ -46,8 +48,7 @@ public R request(StandartClientWebSocketService service) throws Exception {
|
|||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected R requestDo(StandartClientWebSocketService service) throws Exception
|
||||
{
|
||||
protected R requestDo(StandartClientWebSocketService service) throws Exception {
|
||||
return (R) service.sendRequest(this);
|
||||
}
|
||||
|
||||
|
|
|
@ -81,6 +81,7 @@ public AuthRequest(String login, byte[] encryptedPassword, String auth_id, Conne
|
|||
this.customText = "";
|
||||
this.getSession = false;
|
||||
}
|
||||
|
||||
public AuthRequest(String login, String password, String auth_id, ConnectTypes authType) {
|
||||
this.login = login;
|
||||
this.password = password;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
import ru.gravit.launcher.request.Request;
|
||||
import ru.gravit.launcher.request.websockets.RequestInterface;
|
||||
|
||||
public class RestoreSessionRequest extends Request<RestoreSessionRequestEvent> implements RequestInterface {
|
||||
public class RestoreSessionRequest extends Request<RestoreSessionRequestEvent> implements RequestInterface {
|
||||
@LauncherNetworkAPI
|
||||
public long session;
|
||||
|
||||
|
|
|
@ -53,8 +53,7 @@ public static void update(LauncherRequestEvent result) throws IOException {
|
|||
try {
|
||||
ListDownloader downloader = new ListDownloader();
|
||||
downloader.downloadOne(result.url, BINARY_PATH);
|
||||
} catch(Throwable e)
|
||||
{
|
||||
} catch (Throwable e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -175,13 +175,11 @@ public UpdateRequestEvent requestDo(StandartClientWebSocketService service) thro
|
|||
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().equals(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))
|
||||
{
|
||||
} else if (entry.getType().equals(HashedEntry.Type.DIR)) {
|
||||
try {
|
||||
Files.createDirectories(dir.resolve(path));
|
||||
} catch (IOException ex) {
|
||||
|
@ -193,9 +191,14 @@ else if(entry.getType().equals(HashedEntry.Type.DIR))
|
|||
startTime = Instant.now();
|
||||
updateState("UnknownFile", 0L, 100);
|
||||
ListDownloader listDownloader = new ListDownloader();
|
||||
listDownloader.download(e.url, adds, dir, this::updateState, (add) -> {
|
||||
totalDownloaded += add;
|
||||
});
|
||||
if(e.zip && !adds.isEmpty())
|
||||
{
|
||||
listDownloader.downloadZip(e.url, dir, this::updateState, (add) -> totalDownloaded += add);
|
||||
}
|
||||
else
|
||||
{
|
||||
listDownloader.download(e.url, adds, dir, this::updateState, (add) -> totalDownloaded += add);
|
||||
}
|
||||
deleteExtraDir(dir, diff.extra, diff.extra.flag);
|
||||
LogHelper.debug("Update success");
|
||||
return e;
|
||||
|
|
|
@ -18,14 +18,14 @@ class Entry {
|
|||
@LauncherNetworkAPI
|
||||
String client;
|
||||
}
|
||||
|
||||
@LauncherNetworkAPI
|
||||
private final Entry[] list;
|
||||
|
||||
@LauncherAPI
|
||||
public BatchProfileByUsernameRequest(String... usernames) throws IOException {
|
||||
this.list = new Entry[usernames.length];
|
||||
for(int i=0;i<usernames.length;++i)
|
||||
{
|
||||
for (int i = 0; i < usernames.length; ++i) {
|
||||
this.list[i].client = "";
|
||||
this.list[i].username = usernames[i];
|
||||
}
|
||||
|
|
|
@ -41,16 +41,13 @@ public ClientJSONPoint(URI uri) throws SSLException {
|
|||
if (!"ws".equals(protocol) && !"wss".equals(protocol)) {
|
||||
throw new IllegalArgumentException("Unsupported protocol: " + protocol);
|
||||
}
|
||||
if("wss".equals(protocol))
|
||||
{
|
||||
if ("wss".equals(protocol)) {
|
||||
ssl = true;
|
||||
}
|
||||
if(uri.getPort() == -1)
|
||||
{
|
||||
if("ws".equals(protocol)) port = 80;
|
||||
if (uri.getPort() == -1) {
|
||||
if ("ws".equals(protocol)) port = 80;
|
||||
else port = 443;
|
||||
}
|
||||
else port = uri.getPort();
|
||||
} else port = uri.getPort();
|
||||
final SslContext sslCtx;
|
||||
if (ssl) {
|
||||
sslCtx = SslContextBuilder.forClient().build();
|
||||
|
@ -68,7 +65,7 @@ public void initChannel(SocketChannel ch) throws Exception {
|
|||
pipeline.addLast("aggregator", new HttpObjectAggregator(65536));
|
||||
pipeline.addLast("ws-handler", webSocketClientHandler);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
public void open() throws Exception {
|
||||
|
@ -76,24 +73,26 @@ public void open() throws Exception {
|
|||
webSocketClientHandler =
|
||||
new WebSocketClientHandler(
|
||||
WebSocketClientHandshakerFactory.newHandshaker(
|
||||
uri, WebSocketVersion.V13, null, false, EmptyHttpHeaders.INSTANCE, 1280000), this);
|
||||
uri, WebSocketVersion.V13, null, false, EmptyHttpHeaders.INSTANCE, 12800000), this);
|
||||
ch = bootstrap.connect(uri.getHost(), port).sync().channel();
|
||||
webSocketClientHandler.handshakeFuture().sync();
|
||||
}
|
||||
public ChannelFuture send(String text)
|
||||
{
|
||||
|
||||
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())
|
||||
{
|
||||
if (ch != null && ch.isActive()) {
|
||||
ch.writeAndFlush(new CloseWebSocketFrame());
|
||||
ch.closeFuture().sync();
|
||||
}
|
||||
|
|
|
@ -60,24 +60,22 @@ void onMessage(String message) {
|
|||
@Override
|
||||
void onDisconnect() {
|
||||
LogHelper.info("WebSocket client disconnect");
|
||||
if(onCloseCallback != null) onCloseCallback.onClose(0,"unsupported param", !isClosed);
|
||||
if (onCloseCallback != null) onCloseCallback.onClose(0, "unsupported param", !isClosed);
|
||||
}
|
||||
|
||||
@Override
|
||||
void onOpen() throws Exception {
|
||||
synchronized (onConnect)
|
||||
{
|
||||
synchronized (onConnect) {
|
||||
onConnect.notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
public interface OnCloseCallback
|
||||
{
|
||||
public interface OnCloseCallback {
|
||||
void onClose(int code, String reason, boolean remote);
|
||||
}
|
||||
public interface ReconnectCallback
|
||||
{
|
||||
|
||||
public interface ReconnectCallback {
|
||||
void onReconnect() throws IOException;
|
||||
}
|
||||
|
||||
|
@ -126,8 +124,8 @@ public void registerResults() {
|
|||
public void registerHandler(EventHandler eventHandler) {
|
||||
handlers.add(eventHandler);
|
||||
}
|
||||
public void waitIfNotConnected()
|
||||
{
|
||||
|
||||
public void waitIfNotConnected() {
|
||||
/*if(!isOpen() && !isClosed() && !isClosing())
|
||||
{
|
||||
LogHelper.warning("WebSocket not connected. Try wait onConnect object");
|
||||
|
@ -144,7 +142,7 @@ public void waitIfNotConnected()
|
|||
|
||||
public void sendObject(Object obj) throws IOException {
|
||||
waitIfNotConnected();
|
||||
if(ch == null || !ch.isActive()) reconnectCallback.onReconnect();
|
||||
if (ch == null || !ch.isActive()) reconnectCallback.onReconnect();
|
||||
//if(isClosed() && reconnectCallback != null)
|
||||
// reconnectCallback.onReconnect();
|
||||
send(gson.toJson(obj, RequestInterface.class));
|
||||
|
@ -152,7 +150,7 @@ public void sendObject(Object obj) throws IOException {
|
|||
|
||||
public void sendObject(Object obj, Type type) throws IOException {
|
||||
waitIfNotConnected();
|
||||
if(ch == null || !ch.isActive()) reconnectCallback.onReconnect();
|
||||
if (ch == null || !ch.isActive()) reconnectCallback.onReconnect();
|
||||
//if(isClosed() && reconnectCallback != null)
|
||||
// reconnectCallback.onReconnect();
|
||||
send(gson.toJson(obj, type));
|
||||
|
|
|
@ -17,8 +17,7 @@ public JsonRequestAdapter(ClientWebSocketService service) {
|
|||
public RequestInterface deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString();
|
||||
Class<? extends RequestInterface> cls = service.getRequestClass(typename);
|
||||
if(cls == null)
|
||||
{
|
||||
if (cls == null) {
|
||||
LogHelper.error("Request type %s not found", typename);
|
||||
}
|
||||
|
||||
|
|
|
@ -18,8 +18,7 @@ public JsonResultAdapter(ClientWebSocketService service) {
|
|||
public ResultInterface deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
|
||||
String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString();
|
||||
Class<? extends ResultInterface> cls = service.getResultClass(typename);
|
||||
if(cls == null)
|
||||
{
|
||||
if (cls == null) {
|
||||
LogHelper.error("Result type %s not found", typename);
|
||||
}
|
||||
|
||||
|
|
|
@ -16,20 +16,20 @@
|
|||
|
||||
public class StandartClientWebSocketService extends ClientWebSocketService {
|
||||
public WaitEventHandler waitEventHandler = new WaitEventHandler();
|
||||
|
||||
public StandartClientWebSocketService(GsonBuilder gsonBuilder, String address, int i) throws SSLException {
|
||||
super(gsonBuilder, address, i);
|
||||
}
|
||||
public class RequestFuture implements Future<ResultInterface>
|
||||
{
|
||||
|
||||
public class RequestFuture implements Future<ResultInterface> {
|
||||
public final WaitEventHandler.ResultEvent event;
|
||||
public boolean isCanceled = false;
|
||||
|
||||
@SuppressWarnings("rawtypes")
|
||||
public RequestFuture(RequestInterface request) throws IOException {
|
||||
public RequestFuture(RequestInterface request) throws IOException {
|
||||
event = new WaitEventHandler.ResultEvent();
|
||||
event.type = request.getType();
|
||||
if(request instanceof Request)
|
||||
{
|
||||
if (request instanceof Request) {
|
||||
event.uuid = ((Request) request).requestUUID;
|
||||
}
|
||||
waitEventHandler.requests.add(event);
|
||||
|
@ -55,7 +55,7 @@ public boolean isDone() {
|
|||
|
||||
@Override
|
||||
public ResultInterface get() throws InterruptedException, ExecutionException {
|
||||
if(isCanceled) return null;
|
||||
if (isCanceled) return null;
|
||||
while (!event.ready) {
|
||||
synchronized (event) {
|
||||
event.wait();
|
||||
|
@ -72,7 +72,7 @@ public ResultInterface get() throws InterruptedException, ExecutionException {
|
|||
|
||||
@Override
|
||||
public ResultInterface get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException {
|
||||
if(isCanceled) return null;
|
||||
if (isCanceled) return null;
|
||||
while (!event.ready) {
|
||||
synchronized (event) {
|
||||
event.wait(timeout);
|
||||
|
@ -87,6 +87,7 @@ public ResultInterface get(long timeout, TimeUnit unit) throws InterruptedExcept
|
|||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
public ResultInterface sendRequest(RequestInterface request) throws IOException, InterruptedException {
|
||||
RequestFuture future = new RequestFuture(request);
|
||||
ResultInterface result;
|
||||
|
@ -97,6 +98,7 @@ public ResultInterface sendRequest(RequestInterface request) throws IOException,
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public RequestFuture asyncSendRequest(RequestInterface request) throws IOException {
|
||||
return new RequestFuture(request);
|
||||
}
|
||||
|
@ -112,17 +114,14 @@ public static StandartClientWebSocketService initWebSockets(String address, bool
|
|||
service.registerResults();
|
||||
service.registerRequests();
|
||||
service.registerHandler(service.waitEventHandler);
|
||||
if(!async)
|
||||
{
|
||||
if (!async) {
|
||||
try {
|
||||
service.open();
|
||||
LogHelper.debug("Connect to %s", address);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
try {
|
||||
service.open();
|
||||
} catch (Exception e) {
|
||||
|
|
|
@ -14,17 +14,16 @@ public class WaitEventHandler implements ClientWebSocketService.EventHandler {
|
|||
public void process(ResultInterface result) {
|
||||
LogHelper.debug("Processing event %s type", result.getType());
|
||||
UUID checkUUID = null;
|
||||
if(result instanceof RequestEvent)
|
||||
{
|
||||
if (result instanceof RequestEvent) {
|
||||
RequestEvent event = (RequestEvent) result;
|
||||
checkUUID = event.requestUUID;
|
||||
if(checkUUID != null)
|
||||
LogHelper.debug("Event UUID: %s found", checkUUID.toString());
|
||||
if (checkUUID != null)
|
||||
LogHelper.debug("Event UUID: %s found", checkUUID.toString());
|
||||
}
|
||||
for (ResultEvent r : requests) {
|
||||
if(r.uuid != null)
|
||||
if (r.uuid != null)
|
||||
LogHelper.debug("Request UUID found: %s", r.uuid.toString());
|
||||
if( (r.uuid != null && r.uuid.equals(checkUUID)) || ( checkUUID == null && (r.type.equals(result.getType()) || result.getType().equals("error") )) ) {
|
||||
if ((r.uuid != null && r.uuid.equals(checkUUID)) || (checkUUID == null && (r.type.equals(result.getType()) || result.getType().equals("error")))) {
|
||||
LogHelper.debug("Event %s type", r.type);
|
||||
synchronized (r) {
|
||||
r.result = result;
|
||||
|
|
|
@ -1,19 +1,11 @@
|
|||
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.channel.*;
|
||||
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.handler.codec.http.websocketx.*;
|
||||
import io.netty.util.CharsetUtil;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public class WebSocketClientHandler extends SimpleChannelInboundHandler<Object> {
|
||||
|
||||
private final WebSocketClientHandshaker handshaker;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
apply from: '../test_support.gradle'
|
||||
|
||||
dependencies {
|
||||
compile project(':LaunchServer')
|
||||
compile project(':LaunchServer')
|
||||
}
|
||||
|
||||
|
|
|
@ -1,36 +1,35 @@
|
|||
package ru.gravit.launcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.io.TempDir;
|
||||
|
||||
import ru.gravit.launcher.test.utils.EXENonWarningLauncherBinary;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
|
||||
public class StartTest {
|
||||
@TempDir
|
||||
public Path dir;
|
||||
|
||||
@BeforeAll
|
||||
public static void prepare() {
|
||||
LogHelper.removeStdOutput();
|
||||
LaunchServer.defaultLauncherEXEBinaryClass = EXENonWarningLauncherBinary.class;
|
||||
LogHelper.removeStdOutput();
|
||||
LaunchServer.defaultLauncherEXEBinaryClass = EXENonWarningLauncherBinary.class;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkLaunchServerStarts() {
|
||||
try {
|
||||
LaunchServer srv = new LaunchServer(dir, true, new String[]{"checkInstall"});
|
||||
srv.run();
|
||||
srv.commandHandler.eval(new String[]{"checkInstall"}, false);
|
||||
srv.close();
|
||||
} catch (InvalidKeySpecException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkLaunchServerStarts() {
|
||||
try {
|
||||
LaunchServer srv = new LaunchServer(dir, true, new String[] { "checkInstall" });
|
||||
srv.run();
|
||||
srv.commandHandler.eval(new String[] { "checkInstall" }, false);
|
||||
srv.close();
|
||||
} catch (InvalidKeySpecException | IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2
Radon
2
Radon
|
@ -1 +1 @@
|
|||
Subproject commit 6410af8044e7346e06f546dc04636b631fa7584c
|
||||
Subproject commit 60fa1c6694b570dda50056b1e2fe18fcdb0f8be0
|
|
@ -4,8 +4,8 @@
|
|||
String mainAgentName = "ru.gravit.launcher.server.ServerAgent"
|
||||
|
||||
configurations {
|
||||
pack
|
||||
compile.extendsFrom pack
|
||||
pack
|
||||
compile.extendsFrom pack
|
||||
}
|
||||
|
||||
repositories {
|
||||
|
@ -18,7 +18,7 @@
|
|||
targetCompatibility = '1.8'
|
||||
|
||||
jar {
|
||||
classifier = 'clean'
|
||||
classifier = 'clean'
|
||||
manifest.attributes("Main-Class": mainClassName,
|
||||
"Premain-Class": mainAgentName,
|
||||
"Can-Redefine-Classes": "true",
|
||||
|
@ -28,17 +28,17 @@
|
|||
|
||||
dependencies {
|
||||
pack project(':LauncherAuthlib')
|
||||
pack 'org.apache.httpcomponents:httpclient:4.5.7'
|
||||
pack 'io.netty:netty-all:4.1.36.Final'
|
||||
pack 'org.apache.httpcomponents:httpclient:4.5.7'
|
||||
pack 'io.netty:netty-all:4.1.36.Final'
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
classifier = null
|
||||
relocate 'io.netty', 'ru.gravit.repackage.io.netty'
|
||||
configurations = [project.configurations.pack]
|
||||
exclude 'module-info.class'
|
||||
}
|
||||
|
||||
classifier = null
|
||||
relocate 'io.netty', 'ru.gravit.repackage.io.netty'
|
||||
configurations = [project.configurations.pack]
|
||||
exclude 'module-info.class'
|
||||
}
|
||||
|
||||
build.dependsOn tasks.shadowJar
|
||||
|
||||
build.dependsOn tasks.shadowJar
|
||||
|
|
@ -3,6 +3,7 @@
|
|||
import ru.gravit.launcher.ClientPermissions;
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.launcher.LauncherConfig;
|
||||
import ru.gravit.launcher.config.JsonConfigurable;
|
||||
import ru.gravit.launcher.events.request.ProfilesRequestEvent;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.request.Request;
|
||||
|
@ -11,7 +12,6 @@
|
|||
import ru.gravit.launcher.request.update.ProfilesRequest;
|
||||
import ru.gravit.launcher.server.setup.ServerWrapperSetup;
|
||||
import ru.gravit.utils.PublicURLClassLoader;
|
||||
import ru.gravit.launcher.config.JsonConfigurable;
|
||||
import ru.gravit.utils.helper.CommonHelper;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
@ -157,8 +157,7 @@ public void run(String... args) throws Throwable {
|
|||
else mainClass = Class.forName(classname);
|
||||
MethodHandle mainMethod = MethodHandles.publicLookup().findStatic(mainClass, "main", MethodType.methodType(void.class, String[].class));
|
||||
modulesManager.postInitModules();
|
||||
if(config.websocket.enabled)
|
||||
{
|
||||
if (config.websocket.enabled) {
|
||||
Request.service.reconnectCallback = () ->
|
||||
{
|
||||
LogHelper.debug("WebSocket connect closed. Try reconnect");
|
||||
|
@ -194,8 +193,7 @@ public void updateLauncherConfig() {
|
|||
LauncherConfig cfg = null;
|
||||
try {
|
||||
cfg = new LauncherConfig(config.websocket.address, SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile)), new HashMap<>(), config.projectname);
|
||||
if(config.websocket != null && config.websocket.enabled)
|
||||
{
|
||||
if (config.websocket != null && config.websocket.enabled) {
|
||||
cfg.isNettyEnabled = true;
|
||||
cfg.address = config.websocket.address;
|
||||
}
|
||||
|
@ -261,8 +259,8 @@ public static final class Config {
|
|||
public String auth_id = "";
|
||||
public LauncherConfig.LauncherEnvironment env;
|
||||
}
|
||||
public static final class WebSocketConf
|
||||
{
|
||||
|
||||
public static final class WebSocketConf {
|
||||
public boolean enabled;
|
||||
public String address;
|
||||
}
|
||||
|
|
|
@ -22,7 +22,7 @@ public ServerWrapperCommands() throws IOException {
|
|||
// Set command handler
|
||||
CommandHandler localCommandHandler;
|
||||
try {
|
||||
Class.forName("jline.Terminal");
|
||||
Class.forName("org.jline.terminal.Terminal");
|
||||
|
||||
// JLine2 available
|
||||
localCommandHandler = new JLineCommandHandler();
|
||||
|
|
|
@ -25,14 +25,14 @@ public void run() throws IOException {
|
|||
Path jarPath = Paths.get(jarName);
|
||||
String mainClassName = null;
|
||||
try (JarFile file = new JarFile(jarPath.toFile())) {
|
||||
URL jarURL = jarPath.toUri().toURL();
|
||||
urlClassLoader = new PublicURLClassLoader(new URL[]{jarURL});
|
||||
LogHelper.info("Check jar MainClass");
|
||||
mainClassName = file.getManifest().getMainAttributes().getValue("Main-Class");
|
||||
if (mainClassName == null) {
|
||||
LogHelper.error("Main-Class not found in MANIFEST");
|
||||
return;
|
||||
}
|
||||
URL jarURL = jarPath.toUri().toURL();
|
||||
urlClassLoader = new PublicURLClassLoader(new URL[]{jarURL});
|
||||
LogHelper.info("Check jar MainClass");
|
||||
mainClassName = file.getManifest().getMainAttributes().getValue("Main-Class");
|
||||
if (mainClassName == null) {
|
||||
LogHelper.error("Main-Class not found in MANIFEST");
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Class.forName(mainClassName, false, urlClassLoader);
|
||||
} catch (ClassNotFoundException e) {
|
||||
|
|
46
build.gradle
46
build.gradle
|
@ -3,33 +3,33 @@
|
|||
}
|
||||
|
||||
configure(subprojects.findAll { it.name != 'modules' && it.name != 'Radon' }) {
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'idea'
|
||||
apply plugin: 'eclipse'
|
||||
apply plugin: 'java'
|
||||
|
||||
group = 'ru.gravit'
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url 'http://oss.sonatype.org/content/groups/public' }
|
||||
maven {
|
||||
url "http://clojars.org/repo/"
|
||||
}
|
||||
}
|
||||
repositories {
|
||||
mavenCentral()
|
||||
maven { url 'http://oss.sonatype.org/content/groups/public' }
|
||||
maven {
|
||||
url "http://clojars.org/repo/"
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
apt
|
||||
aptCompileOnly
|
||||
aptOnly
|
||||
aptOnly.extendsFrom apt, aptCompileOnly
|
||||
compile.extendsFrom apt
|
||||
compileOnly.extendsFrom aptCompileOnly
|
||||
}
|
||||
configurations {
|
||||
apt
|
||||
aptCompileOnly
|
||||
aptOnly
|
||||
aptOnly.extendsFrom apt, aptCompileOnly
|
||||
compile.extendsFrom apt
|
||||
compileOnly.extendsFrom aptCompileOnly
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = "UTF-8"
|
||||
options.annotationProcessorPath = configurations.aptOnly
|
||||
}
|
||||
tasks.withType(JavaCompile) {
|
||||
options.encoding = "UTF-8"
|
||||
options.annotationProcessorPath = configurations.aptOnly
|
||||
}
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
@ -39,7 +39,7 @@
|
|||
}
|
||||
|
||||
wrapper {
|
||||
distributionType = Wrapper.DistributionType.ALL
|
||||
distributionType = Wrapper.DistributionType.ALL
|
||||
}
|
||||
|
||||
defaultTasks 'build'
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue