Compare commits

..

No commits in common. "3b8c01835dd517b292fe7a48a987b9c38a9943db" and "c6f8793031e5176be9bd483417b3362b3381beee" have entirely different histories.

184 changed files with 2532 additions and 662 deletions

View file

@ -50,18 +50,17 @@
} }
} }
tasks.register('sourcesJar', Jar) { task sourcesJar(type: Jar) {
from sourceSets.main.allJava from sourceSets.main.allJava
archiveClassifier.set('sources') archiveClassifier.set('sources')
} }
tasks.register('javadocJar', Jar) { task javadocJar(type: Jar) {
from javadoc from javadoc
archiveClassifier.set('javadoc') archiveClassifier.set('javadoc')
} }
tasks.register('cleanjar', Jar) { task cleanjar(type: Jar, dependsOn: jar) {
dependsOn jar
archiveClassifier.set('clean') archiveClassifier.set('clean')
manifest.attributes("Main-Class": mainClassName, manifest.attributes("Main-Class": mainClassName,
"Premain-Class": mainAgentName, "Premain-Class": mainAgentName,
@ -118,13 +117,13 @@ pack project(':LauncherAPI')
compileOnlyA 'org.apache.logging.log4j:log4j-core:2.14.1' compileOnlyA 'org.apache.logging.log4j:log4j-core:2.14.1'
} }
tasks.register('hikari', Copy) { task hikari(type: Copy) {
duplicatesStrategy = 'EXCLUDE' duplicatesStrategy = 'EXCLUDE'
into "$buildDir/libs/libraries/hikaricp" into "$buildDir/libs/libraries/hikaricp"
from configurations.hikari from configurations.hikari
} }
tasks.register('launch4j', Copy) { task launch4j(type: Copy) {
duplicatesStrategy = 'EXCLUDE' duplicatesStrategy = 'EXCLUDE'
into "$buildDir/libs/libraries/launch4j" into "$buildDir/libs/libraries/launch4j"
from(configurations.launch4j.collect { from(configurations.launch4j.collect {
@ -142,20 +141,20 @@ pack project(':LauncherAPI')
} }
} }
tasks.register('dumpLibs', Copy) { task dumpLibs(type: Copy) {
duplicatesStrategy = 'EXCLUDE' duplicatesStrategy = 'EXCLUDE'
dependsOn tasks.hikari, tasks.launch4j dependsOn tasks.hikari, tasks.launch4j
into "$buildDir/libs/libraries" into "$buildDir/libs/libraries"
from configurations.bundleOnly from configurations.bundleOnly
} }
tasks.register('dumpCompileOnlyLibs', Copy) { task dumpCompileOnlyLibs(type: Copy) {
duplicatesStrategy = 'EXCLUDE' duplicatesStrategy = 'EXCLUDE'
into "$buildDir/libs/launcher-libraries-compile" into "$buildDir/libs/launcher-libraries-compile"
from configurations.compileOnlyA from configurations.compileOnlyA
} }
tasks.register('bundle', Zip) { task bundle(type: Zip) {
duplicatesStrategy = 'EXCLUDE' duplicatesStrategy = 'EXCLUDE'
dependsOn parent.childProjects.Launcher.tasks.build, tasks.dumpLibs, tasks.dumpCompileOnlyLibs, tasks.jar dependsOn parent.childProjects.Launcher.tasks.build, tasks.dumpLibs, tasks.dumpCompileOnlyLibs, tasks.jar
archiveFileName = 'LaunchServer.zip' archiveFileName = 'LaunchServer.zip'
@ -166,7 +165,7 @@ pack project(':LauncherAPI')
from(parent.childProjects.Launcher.tasks.dumpLibs) { into 'launcher-libraries' } from(parent.childProjects.Launcher.tasks.dumpLibs) { into 'launcher-libraries' }
} }
tasks.register('dumpClientLibs', Copy) { task dumpClientLibs(type: Copy) {
dependsOn parent.childProjects.Launcher.tasks.build dependsOn parent.childProjects.Launcher.tasks.build
into "$buildDir/libs/launcher-libraries" into "$buildDir/libs/launcher-libraries"
from parent.childProjects.Launcher.tasks.dumpLibs from parent.childProjects.Launcher.tasks.dumpLibs

View file

@ -121,6 +121,7 @@ public final class LaunchServer implements Runnable, AutoCloseable, Reconfigurab
// Updates and profiles // Updates and profiles
private volatile Set<ClientProfile> profilesList; private volatile Set<ClientProfile> profilesList;
@SuppressWarnings("deprecation")
public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, LaunchServerModulesManager modulesManager, KeyAgreementManager keyAgreementManager, CommandHandler commandHandler, CertificateManager certificateManager) throws IOException { public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, LaunchServerConfig config, LaunchServerRuntimeConfig runtimeConfig, LaunchServerConfigManager launchServerConfigManager, LaunchServerModulesManager modulesManager, KeyAgreementManager keyAgreementManager, CommandHandler commandHandler, CertificateManager certificateManager) throws IOException {
this.dir = directories.dir; this.dir = directories.dir;
this.tmpDir = directories.tmpDir; this.tmpDir = directories.tmpDir;
@ -218,14 +219,7 @@ public void reload(ReloadType type) throws Exception {
}); });
logger.debug("Init components successful"); logger.debug("Init components successful");
} }
if(!type.equals(ReloadType.NO_AUTH)) {
nettyServerSocketHandler.nettyServer.service.forEachActiveChannels((channel, wsHandler) -> {
Client client = wsHandler.getClient();
if(client.auth != null) {
client.auth = config.getAuthProviderPair(client.auth_id);
}
});
}
} }
@Override @Override
@ -242,7 +236,7 @@ public void invoke(String... args) throws Exception {
case "full" -> reload(ReloadType.FULL); case "full" -> reload(ReloadType.FULL);
case "no_auth" -> reload(ReloadType.NO_AUTH); case "no_auth" -> reload(ReloadType.NO_AUTH);
case "no_components" -> reload(ReloadType.NO_COMPONENTS); case "no_components" -> reload(ReloadType.NO_COMPONENTS);
default -> reload(ReloadType.NO_AUTH); default -> reload(ReloadType.FULL);
} }
} }
}; };

View file

@ -21,6 +21,7 @@
import pro.gravit.launchserver.manangers.LaunchServerGsonManager; import pro.gravit.launchserver.manangers.LaunchServerGsonManager;
import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager; import pro.gravit.launchserver.modules.impl.LaunchServerModulesManager;
import pro.gravit.launchserver.socket.WebSocketService; import pro.gravit.launchserver.socket.WebSocketService;
import pro.gravit.utils.Version;
import pro.gravit.utils.command.CommandHandler; import pro.gravit.utils.command.CommandHandler;
import pro.gravit.utils.command.JLineCommandHandler; import pro.gravit.utils.command.JLineCommandHandler;
import pro.gravit.utils.command.StdCommandHandler; import pro.gravit.utils.command.StdCommandHandler;
@ -201,6 +202,7 @@ public static void initGson(LaunchServerModulesManager modulesManager) {
Launcher.gsonManager.initGson(); Launcher.gsonManager.initGson();
} }
@SuppressWarnings("deprecation")
public static void registerAll() { public static void registerAll() {
AuthCoreProvider.registerProviders(); AuthCoreProvider.registerProviders();
PasswordVerifier.registerProviders(); PasswordVerifier.registerProviders();

View file

@ -65,7 +65,7 @@ private static void visit(ClassNode classNode, Map<String, Object> values) {
return newClinitMethod; return newClinitMethod;
}); });
List<MethodNode> constructors = classNode.methods.stream().filter(method -> "<init>".equals(method.name)) List<MethodNode> constructors = classNode.methods.stream().filter(method -> "<init>".equals(method.name))
.toList(); .collect(Collectors.toList());
MethodNode initMethod = constructors.stream().filter(method -> method.invisibleAnnotations != null MethodNode initMethod = constructors.stream().filter(method -> method.invisibleAnnotations != null
&& method.invisibleAnnotations.stream().anyMatch(annotation -> INJECTED_CONSTRUCTOR_DESC.equals(annotation.desc))).findFirst() && method.invisibleAnnotations.stream().anyMatch(annotation -> INJECTED_CONSTRUCTOR_DESC.equals(annotation.desc))).findFirst()
.orElseGet(() -> constructors.stream().filter(method -> method.desc.equals("()V")).findFirst().orElse(null)); .orElseGet(() -> constructors.stream().filter(method -> method.desc.equals("()V")).findFirst().orElse(null));
@ -112,7 +112,7 @@ public void visit(final String name, final Object value) {
} }
List<FieldInsnNode> putStaticNodes = Arrays.stream(initMethod.instructions.toArray()) List<FieldInsnNode> putStaticNodes = Arrays.stream(initMethod.instructions.toArray())
.filter(node -> node instanceof FieldInsnNode && node.getOpcode() == Opcodes.PUTSTATIC).map(p -> (FieldInsnNode) p) .filter(node -> node instanceof FieldInsnNode && node.getOpcode() == Opcodes.PUTSTATIC).map(p -> (FieldInsnNode) p)
.filter(node -> node.owner.equals(classNode.name) && node.name.equals(field.name) && node.desc.equals(field.desc)).toList(); .filter(node -> node.owner.equals(classNode.name) && node.name.equals(field.name) && node.desc.equals(field.desc)).collect(Collectors.toList());
InsnList setter = serializeValue(value); InsnList setter = serializeValue(value);
if (putStaticNodes.isEmpty()) { if (putStaticNodes.isEmpty()) {
setter.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, field.name, field.desc)); setter.add(new FieldInsnNode(Opcodes.PUTSTATIC, classNode.name, field.name, field.desc));
@ -130,7 +130,7 @@ public void visit(final String name, final Object value) {
} }
List<FieldInsnNode> putFieldNodes = Arrays.stream(initMethod.instructions.toArray()) List<FieldInsnNode> putFieldNodes = Arrays.stream(initMethod.instructions.toArray())
.filter(node -> node instanceof FieldInsnNode && node.getOpcode() == Opcodes.PUTFIELD).map(p -> (FieldInsnNode) p) .filter(node -> node instanceof FieldInsnNode && node.getOpcode() == Opcodes.PUTFIELD).map(p -> (FieldInsnNode) p)
.filter(node -> node.owner.equals(classNode.name) && node.name.equals(field.name) && node.desc.equals(field.desc)).toList(); .filter(node -> node.owner.equals(classNode.name) && node.name.equals(field.name) && node.desc.equals(field.desc)).collect(Collectors.toList());
InsnList setter = serializeValue(value); InsnList setter = serializeValue(value);
if (putFieldNodes.isEmpty()) { if (putFieldNodes.isEmpty()) {
setter.insert(new VarInsnNode(Opcodes.ALOAD, 0)); setter.insert(new VarInsnNode(Opcodes.ALOAD, 0));

View file

@ -3,12 +3,10 @@
import pro.gravit.launcher.events.request.AuthRequestEvent; import pro.gravit.launcher.events.request.AuthRequestEvent;
import java.io.IOException; import java.io.IOException;
import java.io.Serial;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
public final class AuthException extends IOException { public final class AuthException extends IOException {
@Serial
private static final long serialVersionUID = -2586107832847245863L; private static final long serialVersionUID = -2586107832847245863L;

View file

@ -4,6 +4,8 @@
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.auth.core.AuthCoreProvider; import pro.gravit.launchserver.auth.core.AuthCoreProvider;
import pro.gravit.launchserver.auth.core.MySQLCoreProvider;
import pro.gravit.launchserver.auth.core.PostgresSQLCoreProvider;
import pro.gravit.launchserver.auth.texture.TextureProvider; import pro.gravit.launchserver.auth.texture.TextureProvider;
import java.io.IOException; import java.io.IOException;
@ -21,6 +23,7 @@ public final class AuthProviderPair {
public transient Set<String> features; public transient Set<String> features;
public String displayName; public String displayName;
public boolean visible = true; public boolean visible = true;
private transient boolean warnOAuthShow = false;
public AuthProviderPair() { public AuthProviderPair() {
} }
@ -53,6 +56,15 @@ public static void getFeatures(Class<?> clazz, Set<String> list) {
} }
} }
public void internalShowOAuthWarnMessage() {
if (!warnOAuthShow) {
if (!(core instanceof MySQLCoreProvider) && !(core instanceof PostgresSQLCoreProvider)) { // MySQL and PostgreSQL upgraded later
logger.warn("AuthCoreProvider {} ({}) not supported OAuth. Legacy session system may be removed in next release", name, core.getClass().getName());
}
warnOAuthShow = true;
}
}
public final <T> T isSupport(Class<T> clazz) { public final <T> T isSupport(Class<T> clazz) {
if (core == null) return null; if (core == null) return null;
T result = null; T result = null;

View file

@ -29,7 +29,7 @@
import java.util.UUID; import java.util.UUID;
public abstract class AbstractSQLCoreProvider extends AuthCoreProvider { public abstract class AbstractSQLCoreProvider extends AuthCoreProvider {
public final transient Logger logger = LogManager.getLogger(); public transient Logger logger = LogManager.getLogger();
public int expireSeconds = 3600; public int expireSeconds = 3600;
public String uuidColumn; public String uuidColumn;
public String usernameColumn; public String usernameColumn;
@ -208,7 +208,7 @@ protected String makeUserCols() {
return String.format("%s, %s, %s, %s, %s", uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, passwordColumn); return String.format("%s, %s, %s, %s, %s", uuidColumn, usernameColumn, accessTokenColumn, serverIDColumn, passwordColumn);
} }
protected void updateAuth(User user, String accessToken) throws IOException { protected boolean updateAuth(User user, String accessToken) throws IOException {
try (Connection c = getSQLConfig().getConnection()) { try (Connection c = getSQLConfig().getConnection()) {
SQLUser SQLUser = (SQLUser) user; SQLUser SQLUser = (SQLUser) user;
SQLUser.accessToken = accessToken; SQLUser.accessToken = accessToken;
@ -216,7 +216,7 @@ protected void updateAuth(User user, String accessToken) throws IOException {
s.setString(1, accessToken); s.setString(1, accessToken);
s.setString(2, user.getUUID().toString()); s.setString(2, user.getUUID().toString());
s.setQueryTimeout(MySQLSourceConfig.TIMEOUT); s.setQueryTimeout(MySQLSourceConfig.TIMEOUT);
s.executeUpdate(); return s.executeUpdate() > 0;
} catch (SQLException e) { } catch (SQLException e) {
throw new IOException(e); throw new IOException(e);
} }
@ -238,7 +238,7 @@ protected boolean updateServerID(User user, String serverID) throws IOException
} }
@Override @Override
public void close() { public void close() throws IOException {
getSQLConfig().close(); getSQLConfig().close();
} }
@ -299,12 +299,12 @@ private List<String> queryRolesNames(String sql, String value) throws SQLExcepti
} }
public static class SQLUser implements User { public static class SQLUser implements User {
protected final UUID uuid; protected UUID uuid;
protected final String username; protected String username;
protected String accessToken; protected String accessToken;
protected String serverId; protected String serverId;
protected final String password; protected String password;
protected final ClientPermissions permissions; protected ClientPermissions permissions;
public SQLUser(UUID uuid, String username, String accessToken, String serverId, String password, ClientPermissions permissions) { public SQLUser(UUID uuid, String username, String accessToken, String serverId, String password, ClientPermissions permissions) {
this.uuid = uuid; this.uuid = uuid;

View file

@ -140,7 +140,7 @@ public void invoke(String... args) throws Exception {
if (instance != null) { if (instance != null) {
map.put("getallusers", new SubCommand("(limit)", "print all users information") { map.put("getallusers", new SubCommand("(limit)", "print all users information") {
@Override @Override
public void invoke(String... args) { public void invoke(String... args) throws Exception {
int max = Integer.MAX_VALUE; int max = Integer.MAX_VALUE;
if (args.length > 0) max = Integer.parseInt(args[0]); if (args.length > 0) max = Integer.parseInt(args[0]);
Iterable<User> users = instance.getAllUsers(); Iterable<User> users = instance.getAllUsers();
@ -316,7 +316,7 @@ public <T> T isSupport(Class<T> clazz) {
} }
@Override @Override
public abstract void close(); public abstract void close() throws IOException;
public static class PasswordVerifyReport { public static class PasswordVerifyReport {
public static final PasswordVerifyReport REQUIRED_2FA = new PasswordVerifyReport(-1); public static final PasswordVerifyReport REQUIRED_2FA = new PasswordVerifyReport(-1);

View file

@ -1,5 +1,6 @@
package pro.gravit.launchserver.auth.core; package pro.gravit.launchserver.auth.core;
import com.google.gson.reflect.TypeToken;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import pro.gravit.launcher.ClientPermissions; import pro.gravit.launcher.ClientPermissions;
@ -317,7 +318,7 @@ public void init(LaunchServer server) {
} }
@Override @Override
public void close() { public void close() throws IOException {
} }
@ -524,6 +525,10 @@ public class HttpUser implements User, UserSupportTextures, UserSupportPropertie
private String serverId; private String serverId;
private String accessToken; private String accessToken;
private ClientPermissions permissions; private ClientPermissions permissions;
@Deprecated
private Texture skin;
@Deprecated
private Texture cloak;
private Map<String, Texture> assets; private Map<String, Texture> assets;
private Map<String, String> properties; private Map<String, String> properties;
private long hwidId; private long hwidId;
@ -547,6 +552,8 @@ public HttpUser(String username, UUID uuid, String serverId, String accessToken,
this.serverId = serverId; this.serverId = serverId;
this.accessToken = accessToken; this.accessToken = accessToken;
this.permissions = permissions; this.permissions = permissions;
this.skin = skin;
this.cloak = cloak;
this.hwidId = hwidId; this.hwidId = hwidId;
} }
@ -556,6 +563,8 @@ public HttpUser(String username, UUID uuid, String serverId, String accessToken,
this.serverId = serverId; this.serverId = serverId;
this.accessToken = accessToken; this.accessToken = accessToken;
this.permissions = permissions; this.permissions = permissions;
this.skin = skin;
this.cloak = cloak;
this.properties = properties; this.properties = properties;
this.hwidId = hwidId; this.hwidId = hwidId;
} }
@ -598,17 +607,30 @@ public ClientPermissions getPermissions() {
@Override @Override
public Texture getSkinTexture() { public Texture getSkinTexture() {
if (assets == null) {
return skin;
}
return assets.get("SKIN"); return assets.get("SKIN");
} }
@Override @Override
public Texture getCloakTexture() { public Texture getCloakTexture() {
if (assets == null) {
return cloak;
}
return assets.get("CAPE"); return assets.get("CAPE");
} }
public Map<String, Texture> getAssets() { public Map<String, Texture> getAssets() {
if (assets == null) { if (assets == null) {
return new HashMap<>(); Map<String, Texture> map = new HashMap<>();
if (skin != null) {
map.put("SKIN", skin);
}
if (cloak != null) {
map.put("CAPE", cloak);
}
return map;
} }
return assets; return assets;
} }

View file

@ -53,7 +53,7 @@ public User getUserByUUID(UUID uuid) {
} }
@Override @Override
public UserSession getUserSessionByOAuthAccessToken(String accessToken) { public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
synchronized (memory) { synchronized (memory) {
for (MemoryUser u : memory) { for (MemoryUser u : memory) {
if (u.accessToken.equals(accessToken)) { if (u.accessToken.equals(accessToken)) {
@ -95,14 +95,14 @@ public AuthManager.AuthReport authorize(String login, AuthResponse.AuthContext c
} }
@Override @Override
protected boolean updateServerID(User user, String serverID) { protected boolean updateServerID(User user, String serverID) throws IOException {
MemoryUser memoryUser = (MemoryUser) user; MemoryUser memoryUser = (MemoryUser) user;
memoryUser.serverId = serverID; memoryUser.serverId = serverID;
return true; return true;
} }
@Override @Override
public User checkServer(Client client, String username, String serverID) { public User checkServer(Client client, String username, String serverID) throws IOException {
synchronized (memory) { synchronized (memory) {
for (MemoryUser u : memory) { for (MemoryUser u : memory) {
if (u.username.equals(username)) { if (u.username.equals(username)) {
@ -116,7 +116,7 @@ public User checkServer(Client client, String username, String serverID) {
} }
@Override @Override
public boolean joinServer(Client client, String username, String accessToken, String serverID) { public boolean joinServer(Client client, String username, String accessToken, String serverID) throws IOException {
return true; return true;
} }
@ -126,16 +126,16 @@ public void init(LaunchServer server) {
} }
@Override @Override
public void close() { public void close() throws IOException {
} }
public static class MemoryUser implements User { public static class MemoryUser implements User {
private final String username; private String username;
private final UUID uuid; private UUID uuid;
private String serverId; private String serverId;
private final String accessToken; private String accessToken;
private final ClientPermissions permissions; private ClientPermissions permissions;
public MemoryUser(String username) { public MemoryUser(String username) {
this.username = username; this.username = username;
@ -188,9 +188,9 @@ public int hashCode() {
} }
public static class MemoryUserSession implements UserSession { public static class MemoryUserSession implements UserSession {
private final String id; private String id;
private final MemoryUser user; private MemoryUser user;
private final long expireIn; private long expireIn;
public MemoryUserSession(MemoryUser user) { public MemoryUserSession(MemoryUser user) {
this.id = SecurityHelper.randomStringToken(); this.id = SecurityHelper.randomStringToken();

View file

@ -17,7 +17,7 @@
public class MergeAuthCoreProvider extends AuthCoreProvider { public class MergeAuthCoreProvider extends AuthCoreProvider {
private transient final Logger logger = LogManager.getLogger(MergeAuthCoreProvider.class); private transient final Logger logger = LogManager.getLogger(MergeAuthCoreProvider.class);
public List<String> list = new ArrayList<>(); public List<String> list = new ArrayList<>();
private final transient List<AuthCoreProvider> providers = new ArrayList<>(); private transient List<AuthCoreProvider> providers = new ArrayList<>();
@Override @Override
public User getUserByUsername(String username) { public User getUserByUsername(String username) {
for(var core : providers) { for(var core : providers) {
@ -67,7 +67,7 @@ public User checkServer(Client client, String username, String serverID) throws
} }
@Override @Override
public boolean joinServer(Client client, String username, String accessToken, String serverID) { public boolean joinServer(Client client, String username, String accessToken, String serverID) throws IOException {
return false; // Authorization not supported return false; // Authorization not supported
} }
@ -84,7 +84,7 @@ public void init(LaunchServer server) {
} }
@Override @Override
public void close() { public void close() throws IOException {
// Providers closed automatically // Providers closed automatically
} }
} }

View file

@ -21,7 +21,7 @@ public User getUserByUUID(UUID uuid) {
} }
@Override @Override
public UserSession getUserSessionByOAuthAccessToken(String accessToken) { public UserSession getUserSessionByOAuthAccessToken(String accessToken) throws OAuthAccessTokenExpired {
return null; return null;
} }
@ -46,12 +46,12 @@ public void init(LaunchServer server) {
} }
@Override @Override
protected boolean updateServerID(User user, String serverID) { protected boolean updateServerID(User user, String serverID) throws IOException {
return false; return false;
} }
@Override @Override
public void close() { public void close() throws IOException {
} }
} }

View file

@ -4,7 +4,7 @@
import pro.gravit.launchserver.auth.core.UserSession; import pro.gravit.launchserver.auth.core.UserSession;
public interface AuthSupportExit extends AuthSupport { public interface AuthSupportExit extends AuthSupport {
void deleteSession(UserSession session); boolean deleteSession(UserSession session);
void exitUser(User user); boolean exitUser(User user);
} }

View file

@ -14,7 +14,7 @@
import java.time.Duration; import java.time.Duration;
public class JsonPasswordVerifier extends PasswordVerifier { public class JsonPasswordVerifier extends PasswordVerifier {
private static final Logger logger = LogManager.getLogger(); private static transient final Logger logger = LogManager.getLogger();
private transient final HttpClient client = HttpClient.newBuilder().build(); private transient final HttpClient client = HttpClient.newBuilder().build();
public String url; public String url;
public String bearerToken; public String bearerToken;

View file

@ -15,6 +15,7 @@
import pro.gravit.launchserver.auth.protect.interfaces.JoinServerProtectHandler; import pro.gravit.launchserver.auth.protect.interfaces.JoinServerProtectHandler;
import pro.gravit.launchserver.auth.protect.interfaces.SecureProtectHandler; import pro.gravit.launchserver.auth.protect.interfaces.SecureProtectHandler;
import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.auth.AuthResponse;
import pro.gravit.launchserver.socket.response.auth.RestoreResponse; import pro.gravit.launchserver.socket.response.auth.RestoreResponse;
import pro.gravit.launchserver.socket.response.secure.HardwareReportResponse; import pro.gravit.launchserver.socket.response.secure.HardwareReportResponse;
@ -26,6 +27,16 @@ public class AdvancedProtectHandler extends StdProtectHandler implements SecureP
public boolean enableHardwareFeature; public boolean enableHardwareFeature;
private transient LaunchServer server; private transient LaunchServer server;
@Override
public boolean allowGetAccessToken(AuthResponse.AuthContext context) {
return (context.authType == AuthResponse.ConnectTypes.CLIENT) && context.client.checkSign;
}
@Override
public void checkLaunchServerLicense() {
}
@Override @Override
public GetSecureLevelInfoRequestEvent onGetSecureLevelInfo(GetSecureLevelInfoRequestEvent event) { public GetSecureLevelInfoRequestEvent onGetSecureLevelInfo(GetSecureLevelInfoRequestEvent event) {
return event; return event;
@ -62,9 +73,11 @@ public void onHardwareReport(HardwareReportResponse response, Client client) {
} }
client.trustLevel.hardwareInfo = hardware.getHardwareInfo(); client.trustLevel.hardwareInfo = hardware.getHardwareInfo();
response.sendResult(new HardwareReportRequestEvent(createHardwareToken(client.username, hardware))); response.sendResult(new HardwareReportRequestEvent(createHardwareToken(client.username, hardware)));
return;
} else { } else {
logger.error("AuthCoreProvider not supported hardware"); logger.error("AuthCoreProvider not supported hardware");
response.sendError("AuthCoreProvider not supported hardware"); response.sendError("AuthCoreProvider not supported hardware");
return;
} }
} }
} }
@ -100,6 +113,10 @@ public void init(LaunchServer server) {
this.server = server; this.server = server;
} }
@Override
public void close() {
}
public String createHardwareToken(String username, UserHardware hardware) { public String createHardwareToken(String username, UserHardware hardware) {
return Jwts.builder() return Jwts.builder()
.setIssuer("LaunchServer") .setIssuer("LaunchServer")
@ -121,10 +138,12 @@ public String createPublicKeyToken(String username, byte[] publicKey) {
} }
public static class HardwareInfoTokenVerifier implements RestoreResponse.ExtendedTokenProvider { public static class HardwareInfoTokenVerifier implements RestoreResponse.ExtendedTokenProvider {
private transient final LaunchServer server;
private transient final Logger logger = LogManager.getLogger(); private transient final Logger logger = LogManager.getLogger();
private final JwtParser parser; private final JwtParser parser;
public HardwareInfoTokenVerifier(LaunchServer server) { public HardwareInfoTokenVerifier(LaunchServer server) {
this.server = server;
this.parser = Jwts.parserBuilder() this.parser = Jwts.parserBuilder()
.requireIssuer("LaunchServer") .requireIssuer("LaunchServer")
.setSigningKey(server.keyAgreementManager.ecdsaPublicKey) .setSigningKey(server.keyAgreementManager.ecdsaPublicKey)
@ -153,10 +172,12 @@ public boolean accept(Client client, AuthProviderPair pair, String extendedToken
} }
public static class PublicKeyTokenVerifier implements RestoreResponse.ExtendedTokenProvider { public static class PublicKeyTokenVerifier implements RestoreResponse.ExtendedTokenProvider {
private transient final LaunchServer server;
private transient final Logger logger = LogManager.getLogger(); private transient final Logger logger = LogManager.getLogger();
private final JwtParser parser; private final JwtParser parser;
public PublicKeyTokenVerifier(LaunchServer server) { public PublicKeyTokenVerifier(LaunchServer server) {
this.server = server;
this.parser = Jwts.parserBuilder() this.parser = Jwts.parserBuilder()
.requireIssuer("LaunchServer") .requireIssuer("LaunchServer")
.setSigningKey(server.keyAgreementManager.ecdsaPublicKey) .setSigningKey(server.keyAgreementManager.ecdsaPublicKey)

View file

@ -9,4 +9,8 @@ public boolean allowGetAccessToken(AuthResponse.AuthContext context) {
return true; return true;
} }
@Override
public void checkLaunchServerLicense() {
// None
}
} }

View file

@ -20,6 +20,8 @@ public static void registerHandlers() {
public abstract boolean allowGetAccessToken(AuthResponse.AuthContext context); public abstract boolean allowGetAccessToken(AuthResponse.AuthContext context);
public abstract void checkLaunchServerLicense(); //Выдает SecurityException при ошибке проверки лицензии
public void init(LaunchServer server) { public void init(LaunchServer server) {
} }

View file

@ -20,6 +20,11 @@ public boolean allowGetAccessToken(AuthResponse.AuthContext context) {
return (context.authType == AuthResponse.ConnectTypes.CLIENT) && context.client.checkSign; return (context.authType == AuthResponse.ConnectTypes.CLIENT) && context.client.checkSign;
} }
@Override
public void checkLaunchServerLicense() {
}
@Override @Override
public void init(LaunchServer server) { public void init(LaunchServer server) {
if (profileWhitelist != null && profileWhitelist.size() > 0) { if (profileWhitelist != null && profileWhitelist.size() > 0) {
@ -54,6 +59,7 @@ private boolean isWhitelisted(String property, ClientProfile profile, Client cli
} }
} }
List<String> allowedUsername = profileWhitelist.get(profile.getTitle()); List<String> allowedUsername = profileWhitelist.get(profile.getTitle());
return allowedUsername != null && allowedUsername.contains(client.username); if (allowedUsername != null && allowedUsername.contains(client.username)) return true;
return false;
} }
} }

View file

@ -15,24 +15,24 @@
import java.util.UUID; import java.util.UUID;
public class JsonTextureProvider extends TextureProvider { public class JsonTextureProvider extends TextureProvider {
private static final Type MAP_TYPE = new TypeToken<Map<String, Texture>>() { private transient static final Type MAP_TYPE = new TypeToken<Map<String, Texture>>() {
}.getType(); }.getType();
private transient final Logger logger = LogManager.getLogger(); private transient final Logger logger = LogManager.getLogger();
public String url; public String url;
@Override @Override
public void close() { public void close() throws IOException {
//None //None
} }
@Override @Override
public Texture getCloakTexture(UUID uuid, String username, String client) { public Texture getCloakTexture(UUID uuid, String username, String client) throws IOException {
logger.warn("Ineffective get cloak texture for {}", username); logger.warn("Ineffective get cloak texture for {}", username);
return getAssets(uuid, username, client).get("CAPE"); return getAssets(uuid, username, client).get("CAPE");
} }
@Override @Override
public Texture getSkinTexture(UUID uuid, String username, String client) { public Texture getSkinTexture(UUID uuid, String username, String client) throws IOException {
logger.warn("Ineffective get skin texture for {}", username); logger.warn("Ineffective get skin texture for {}", username);
return getAssets(uuid, username, client).get("SKIN"); return getAssets(uuid, username, client).get("SKIN");
} }

View file

@ -29,7 +29,7 @@ public RequestTextureProvider(String skinURL, String cloakURL) {
private static Texture getTexture(String url, boolean cloak) throws IOException { private static Texture getTexture(String url, boolean cloak) throws IOException {
try { try {
return new Texture(url, cloak, null); return new Texture(url, cloak);
} catch (FileNotFoundException ignored) { } catch (FileNotFoundException ignored) {
return null; // Simply not found return null; // Simply not found
} }
@ -37,7 +37,7 @@ private static Texture getTexture(String url, boolean cloak) throws IOException
private static Texture getTexture(String url, Path local, boolean cloak) throws IOException { private static Texture getTexture(String url, Path local, boolean cloak) throws IOException {
try { try {
return new Texture(url, local, cloak, null); return new Texture(url, local, cloak);
} catch (FileNotFoundException ignored) { } catch (FileNotFoundException ignored) {
return null; // Simply not found return null; // Simply not found
} }
@ -60,8 +60,7 @@ public Texture getCloakTexture(UUID uuid, String username, String client) throws
if (cloakLocalPath == null) { if (cloakLocalPath == null) {
return getTexture(textureUrl, true); return getTexture(textureUrl, true);
} else { } else {
String path = getTextureURL(cloakLocalPath, uuid, username, client); return getTexture(textureUrl, Paths.get(cloakLocalPath), true);
return getTexture(textureUrl, Paths.get(path), true);
} }
} }
@ -71,8 +70,7 @@ public Texture getSkinTexture(UUID uuid, String username, String client) throws
if (skinLocalPath == null) { if (skinLocalPath == null) {
return getTexture(textureUrl, false); return getTexture(textureUrl, false);
} else { } else {
String path = getTextureURL(skinLocalPath, uuid, username, client); return getTexture(textureUrl, Paths.get(skinLocalPath), false);
return getTexture(textureUrl, Paths.get(path), false);
} }
} }
} }

View file

@ -86,7 +86,7 @@ public void build(Path target, boolean deleteTempFiles) throws IOException {
long time_task_end = System.currentTimeMillis(); long time_task_end = System.currentTimeMillis();
long time_task = time_task_end - time_this; long time_task = time_task_end - time_this;
time_this = time_task_end; time_this = time_task_end;
if (isNeedDelete && deleteTempFiles && oldPath != thisPath) Files.deleteIfExists(oldPath); if (isNeedDelete && deleteTempFiles) Files.deleteIfExists(oldPath);
isNeedDelete = task.allowDelete(); isNeedDelete = task.allowDelete();
logger.info("Task {} processed from {} millis", task.getName(), time_task); logger.info("Task {} processed from {} millis", task.getName(), time_task);
} }

View file

@ -16,6 +16,7 @@
public final class JARLauncherBinary extends LauncherBinary { public final class JARLauncherBinary extends LauncherBinary {
public final AtomicLong count; public final AtomicLong count;
public final Path runtimeDir; public final Path runtimeDir;
public final Path guardDir;
public final Path buildDir; public final Path buildDir;
public final List<Path> coreLibs; public final List<Path> coreLibs;
public final List<Path> addonLibs; public final List<Path> addonLibs;
@ -26,6 +27,7 @@ public JARLauncherBinary(LaunchServer server) throws IOException {
super(server, resolve(server, ".jar"), "Launcher-%s-%d.jar"); super(server, resolve(server, ".jar"), "Launcher-%s-%d.jar");
count = new AtomicLong(0); count = new AtomicLong(0);
runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR); runtimeDir = server.dir.resolve(Launcher.RUNTIME_DIR);
guardDir = server.dir.resolve(Launcher.GUARD_DIR);
buildDir = server.dir.resolve("build"); buildDir = server.dir.resolve("build");
coreLibs = new ArrayList<>(); coreLibs = new ArrayList<>();
addonLibs = new ArrayList<>(); addonLibs = new ArrayList<>();

View file

@ -4,9 +4,12 @@
import pro.gravit.utils.helper.IOHelper; import pro.gravit.utils.helper.IOHelper;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream; import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream; import java.util.zip.ZipOutputStream;

View file

@ -72,6 +72,7 @@ public Path process(Path inputJar) throws IOException {
} else { } else {
context.pushDir(server.launcherBinary.runtimeDir, Launcher.RUNTIME_DIR, runtime, false); context.pushDir(server.launcherBinary.runtimeDir, Launcher.RUNTIME_DIR, runtime, false);
} }
context.pushDir(server.launcherBinary.guardDir, Launcher.GUARD_DIR, runtime, false);
LauncherConfig launcherConfig = new LauncherConfig(server.config.netty.address, server.keyAgreementManager.ecdsaPublicKey, server.keyAgreementManager.rsaPublicKey, runtime, server.config.projectName); LauncherConfig launcherConfig = new LauncherConfig(server.config.netty.address, server.keyAgreementManager.ecdsaPublicKey, server.keyAgreementManager.rsaPublicKey, runtime, server.config.projectName);
context.pushFile(Launcher.CONFIG_FILE, launcherConfig); context.pushFile(Launcher.CONFIG_FILE, launcherConfig);
@ -107,6 +108,7 @@ protected void initProps() {
properties.put("launcher.projectName", server.config.projectName); properties.put("launcher.projectName", server.config.projectName);
properties.put("runtimeconfig.secretKeyClient", SecurityHelper.randomStringAESKey()); properties.put("runtimeconfig.secretKeyClient", SecurityHelper.randomStringAESKey());
properties.put("launcher.port", 32148 + SecurityHelper.newRandom().nextInt(512)); properties.put("launcher.port", 32148 + SecurityHelper.newRandom().nextInt(512));
properties.put("launcher.guardType", server.config.launcher.guardType);
properties.put("launchercore.env", server.config.env); properties.put("launchercore.env", server.config.env);
properties.put("launcher.memory", server.config.launcher.memoryLimit); properties.put("launcher.memory", server.config.launcher.memoryLimit);
properties.put("launcher.customJvmOptions", server.config.launcher.customJvmOptions); properties.put("launcher.customJvmOptions", server.config.launcher.customJvmOptions);
@ -124,8 +126,7 @@ protected void initProps() {
properties.put("runtimeconfig.secureCheckSalt", launcherSalt); properties.put("runtimeconfig.secureCheckSalt", launcherSalt);
if (server.runtime.unlockSecret == null) server.runtime.unlockSecret = SecurityHelper.randomStringToken(); if (server.runtime.unlockSecret == null) server.runtime.unlockSecret = SecurityHelper.randomStringToken();
properties.put("runtimeconfig.unlockSecret", server.runtime.unlockSecret); properties.put("runtimeconfig.unlockSecret", server.runtime.unlockSecret);
server.runtime.buildNumber++;
properties.put("runtimeconfig.buildNumber", server.runtime.buildNumber);
} }
public byte[] transformClass(byte[] bytes, String classname, BuildContext context) { public byte[] transformClass(byte[] bytes, String classname, BuildContext context) {

View file

@ -45,7 +45,7 @@ public Path process(Path inputFile) throws IOException {
throw new RuntimeException(ex); throw new RuntimeException(ex);
} }
})) { })) {
var map = stream.collect(Collectors.toMap(k -> server.launcherPack.relativize(k).toString().replace("\\", "/"), (v) -> v)); var map = stream.collect(Collectors.toMap(k -> server.launcherPack.relativize(k).toString(), (v) -> v));
server.launcherBinary.files.putAll(map); server.launcherBinary.files.putAll(map);
} }
UnpackHelper.unpack(IOHelper.getResourceURL("Launcher.jar"), result); UnpackHelper.unpack(IOHelper.getResourceURL("Launcher.jar"), result);
@ -60,6 +60,7 @@ public boolean allowDelete() {
public void tryUnpack() throws IOException { public void tryUnpack() throws IOException {
logger.info("Unpacking launcher native guard list and runtime"); logger.info("Unpacking launcher native guard list and runtime");
UnpackHelper.unpackZipNoCheck("guard.zip", server.launcherBinary.guardDir);
UnpackHelper.unpackZipNoCheck("runtime.zip", server.launcherBinary.runtimeDir); UnpackHelper.unpackZipNoCheck("runtime.zip", server.launcherBinary.runtimeDir);
} }

View file

@ -26,7 +26,7 @@
public class SignJarTask implements LauncherBuildTask { public class SignJarTask implements LauncherBuildTask {
private static final Logger logger = LogManager.getLogger(); private transient static final Logger logger = LogManager.getLogger();
private final LaunchServerConfig.JarSignerConf config; private final LaunchServerConfig.JarSignerConf config;
private final LaunchServer srv; private final LaunchServer srv;

View file

@ -4,11 +4,8 @@
import me.tongfei.progressbar.ProgressBarBuilder; import me.tongfei.progressbar.ProgressBarBuilder;
import me.tongfei.progressbar.ProgressBarStyle; import me.tongfei.progressbar.ProgressBarStyle;
import pro.gravit.launcher.AsyncDownloader; import pro.gravit.launcher.AsyncDownloader;
import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.LaunchServer;
import pro.gravit.utils.Downloader; import pro.gravit.utils.Downloader;
import pro.gravit.utils.command.CommandException;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
@ -32,13 +29,6 @@ public Command(Map<String, pro.gravit.utils.command.Command> childCommands, Laun
this.server = server; this.server = server;
} }
protected ClientProfile.Version parseClientVersion(String arg) throws CommandException {
if(arg.isEmpty()) {
throw new CommandException("ClientVersion can't be empty");
}
return Launcher.gsonManager.gson.fromJson(arg, ClientProfile.Version.class);
}
protected boolean showApplyDialog(String text) throws IOException { protected boolean showApplyDialog(String text) throws IOException {
System.out.printf("%s [Y/N]:", text); System.out.printf("%s [Y/N]:", text);
String response = server.commandHandler.readLine().toLowerCase(Locale.ROOT); String response = server.commandHandler.readLine().toLowerCase(Locale.ROOT);

View file

@ -10,7 +10,7 @@
import pro.gravit.launchserver.command.Command; import pro.gravit.launchserver.command.Command;
public class DebugCommand extends Command { public class DebugCommand extends Command {
private final transient Logger logger = LogManager.getLogger(); private transient Logger logger = LogManager.getLogger();
public DebugCommand(LaunchServer server) { public DebugCommand(LaunchServer server) {
super(server); super(server);

View file

@ -12,6 +12,7 @@
import pro.gravit.utils.command.basic.HelpCommand; import pro.gravit.utils.command.basic.HelpCommand;
public abstract class CommandHandler extends pro.gravit.utils.command.CommandHandler { public abstract class CommandHandler extends pro.gravit.utils.command.CommandHandler {
@SuppressWarnings("deprecation")
public static void registerCommands(pro.gravit.utils.command.CommandHandler handler, LaunchServer server) { public static void registerCommands(pro.gravit.utils.command.CommandHandler handler, LaunchServer server) {
BaseCommandCategory basic = new BaseCommandCategory(); BaseCommandCategory basic = new BaseCommandCategory();
// Register basic commands // Register basic commands

View file

@ -43,7 +43,7 @@ public void invoke(String... args) throws Exception {
verifyArgs(args, 1); verifyArgs(args, 1);
//Version version = Version.byName(args[0]); //Version version = Version.byName(args[0]);
String versionName = args[0]; String versionName = args[0];
String dirName = IOHelper.verifyFileName(args.length > 1 ? args[1] : "assets"); String dirName = IOHelper.verifyFileName(args[1] != null ? args[1] : "assets");
String type = args.length > 2 ? args[2] : "mojang"; String type = args.length > 2 ? args[2] : "mojang";
Path assetDir = server.updatesDir.resolve(dirName); Path assetDir = server.updatesDir.resolve(dirName);

View file

@ -5,7 +5,6 @@
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import pro.gravit.launcher.Launcher; import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launcher.profiles.ClientProfileVersions;
import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.command.Command; import pro.gravit.launchserver.command.Command;
import pro.gravit.launchserver.helper.MakeProfileHelper; import pro.gravit.launchserver.helper.MakeProfileHelper;
@ -82,9 +81,9 @@ public void invoke(String... args) throws IOException, CommandException {
if (internalVersion.contains("-")) { if (internalVersion.contains("-")) {
internalVersion = internalVersion.substring(0, versionName.indexOf('-')); internalVersion = internalVersion.substring(0, versionName.indexOf('-'));
} }
ClientProfile.Version version = ClientProfile.Version.of(internalVersion); ClientProfile.Version version = ClientProfile.Version.byName(internalVersion);
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_10) <= 0) { if (version.compareTo(ClientProfile.Version.MC164) <= 0) {
logger.warn("Minecraft 1.7.9 and below not supported. Use at your own risk"); logger.warn("Minecraft 1.6.4 and below not supported. Use at your own risk");
} }
MakeProfileHelper.MakeProfileOption[] options = MakeProfileHelper.getMakeProfileOptionsFromDir(clientDir, version, Files.exists(server.updatesDir.resolve("assets"))); MakeProfileHelper.MakeProfileOption[] options = MakeProfileHelper.getMakeProfileOptionsFromDir(clientDir, version, Files.exists(server.updatesDir.resolve("assets")));
for (MakeProfileHelper.MakeProfileOption option : options) { for (MakeProfileHelper.MakeProfileOption option : options) {

View file

@ -32,12 +32,12 @@ public String getUsageDescription() {
@Override @Override
public void invoke(String... args) throws Exception { public void invoke(String... args) throws Exception {
verifyArgs(args, 3); verifyArgs(args, 3);
ClientProfile.Version version = parseClientVersion(args[1]); ClientProfile.Version version = ClientProfile.Version.byName(args[1]);
MakeProfileHelper.MakeProfileOption[] options = MakeProfileHelper.getMakeProfileOptionsFromDir(server.updatesDir.resolve(args[2]), version, Files.exists(server.updatesDir.resolve("assets"))); MakeProfileHelper.MakeProfileOption[] options = MakeProfileHelper.getMakeProfileOptionsFromDir(server.updatesDir.resolve(args[2]), version, Files.exists(server.updatesDir.resolve("assets")));
for (MakeProfileHelper.MakeProfileOption option : options) { for (MakeProfileHelper.MakeProfileOption option : options) {
logger.info("Detected option {}", option); logger.info("Detected option {}", option);
} }
ClientProfile profile = MakeProfileHelper.makeProfile(version, args[0], options); ClientProfile profile = MakeProfileHelper.makeProfile(ClientProfile.Version.byName(args[1]), args[0], options);
try (Writer writer = IOHelper.newWriter(server.profilesDir.resolve(args[0].concat(".json")))) { try (Writer writer = IOHelper.newWriter(server.profilesDir.resolve(args[0].concat(".json")))) {
Launcher.gsonManager.configGson.toJson(profile, writer); Launcher.gsonManager.configGson.toJson(profile, writer);
} }

View file

@ -30,7 +30,7 @@
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class SecurityCheckCommand extends Command { public class SecurityCheckCommand extends Command {
private static final Logger logger = LogManager.getLogger(); private static transient final Logger logger = LogManager.getLogger();
public SecurityCheckCommand(LaunchServer server) { public SecurityCheckCommand(LaunchServer server) {
super(server); super(server);
@ -110,7 +110,7 @@ public void invoke(String... args) {
try { try {
KeyStore keyStore = SignHelper.getStore(new File(config.sign.keyStore).toPath(), config.sign.keyStorePass, config.sign.keyStoreType); KeyStore keyStore = SignHelper.getStore(new File(config.sign.keyStore).toPath(), config.sign.keyStorePass, config.sign.keyStoreType);
Certificate[] certChainPlain = keyStore.getCertificateChain(config.sign.keyAlias); Certificate[] certChainPlain = keyStore.getCertificateChain(config.sign.keyAlias);
List<X509Certificate> certChain = Arrays.stream(certChainPlain).map(e -> (X509Certificate) e).toList(); List<X509Certificate> certChain = Arrays.stream(certChainPlain).map(e -> (X509Certificate) e).collect(Collectors.toList());
X509Certificate cert = certChain.get(0); X509Certificate cert = certChain.get(0);
cert.checkValidity(); cert.checkValidity();
if (certChain.size() <= 1) { if (certChain.size() <= 1) {
@ -169,7 +169,7 @@ public void invoke(String... args) {
bad = true; bad = true;
} }
} else { } else {
if (nextToken.equals("memory_repo") || nextToken.equals(profile.getVersion().toString())) { if (nextToken.equals("memory_repo") || nextToken.equals(profile.getVersion().name)) {
printCheckResult(profileModuleName, String.format("updateExclusions %s not safe. Cheats may be injected very easy!", exc), false); printCheckResult(profileModuleName, String.format("updateExclusions %s not safe. Cheats may be injected very easy!", exc), false);
bad = true; bad = true;
} }

View file

@ -41,7 +41,7 @@ public void invoke(String... args) throws Exception {
Optional<SignJarTask> task = server.launcherBinary.getTaskByClass(SignJarTask.class); Optional<SignJarTask> task = server.launcherBinary.getTaskByClass(SignJarTask.class);
if (task.isEmpty()) throw new IllegalStateException("SignJarTask not found"); if (task.isEmpty()) throw new IllegalStateException("SignJarTask not found");
task.get().sign(server.config.sign, target, tmpSign); task.get().sign(server.config.sign, target, tmpSign);
if (args.length == 1) { if (args.length <= 1) {
logger.info("Move temp jar {} to {}", tmpSign.toString(), target.toString()); logger.info("Move temp jar {} to {}", tmpSign.toString(), target.toString());
Files.deleteIfExists(target); Files.deleteIfExists(target);
Files.move(tmpSign, target); Files.move(tmpSign, target);

View file

@ -25,7 +25,7 @@ public void invoke(String... args) throws Exception {
}); });
this.childCommands.put("server", new SubCommand("[profileName] (authId)", "generate new server token") { this.childCommands.put("server", new SubCommand("[profileName] (authId)", "generate new server token") {
@Override @Override
public void invoke(String... args) { public void invoke(String... args) throws Exception {
AuthProviderPair pair = args.length > 1 ? server.config.getAuthProviderPair(args[1]) : server.config.getAuthProviderPair(); AuthProviderPair pair = args.length > 1 ? server.config.getAuthProviderPair(args[1]) : server.config.getAuthProviderPair();
ClientProfile profile = null; ClientProfile profile = null;
for (ClientProfile p : server.getProfiles()) { for (ClientProfile p : server.getProfiles()) {

View file

@ -28,7 +28,7 @@
import java.util.Map; import java.util.Map;
public class ProGuardComponent extends Component implements AutoCloseable, Reconfigurable { public class ProGuardComponent extends Component implements AutoCloseable, Reconfigurable {
private static final Logger logger = LogManager.getLogger(); private transient static final Logger logger = LogManager.getLogger();
public String modeAfter = "MainBuild"; public String modeAfter = "MainBuild";
public String dir = "proguard"; public String dir = "proguard";
public boolean enabled = true; public boolean enabled = true;
@ -79,7 +79,7 @@ public void init(LaunchServer launchServer) {
} }
@Override @Override
public void close() { public void close() throws Exception {
if (launchServer != null && buildTask != null) { if (launchServer != null && buildTask != null) {
launchServer.launcherBinary.tasks.remove(buildTask); launchServer.launcherBinary.tasks.remove(buildTask);
} }

View file

@ -48,7 +48,7 @@ public boolean hookJoin(JoinServerResponse response, Client client) throws HookE
} }
@Override @Override
public void close() { public void close() throws Exception {
this.server.authHookManager.preHook.unregisterHook(this::hookAuth); this.server.authHookManager.preHook.unregisterHook(this::hookAuth);
this.server.authHookManager.joinServerHook.unregisterHook(this::hookJoin); this.server.authHookManager.joinServerHook.unregisterHook(this::hookJoin);
} }
@ -82,14 +82,14 @@ public void invoke(String... args) throws Exception {
}); });
commands.put("disable", new SubCommand() { commands.put("disable", new SubCommand() {
@Override @Override
public void invoke(String... args) { public void invoke(String... args) throws Exception {
enabled = false; enabled = false;
logger.info("Whitelist disabled"); logger.info("Whitelist disabled");
} }
}); });
commands.put("enable", new SubCommand() { commands.put("enable", new SubCommand() {
@Override @Override
public void invoke(String... args) { public void invoke(String... args) throws Exception {
enabled = true; enabled = true;
logger.info("Whitelist enabled"); logger.info("Whitelist enabled");
} }

View file

@ -24,7 +24,6 @@
import java.util.*; import java.util.*;
public final class LaunchServerConfig { public final class LaunchServerConfig {
private final static List<String> oldMirrorList = List.of("https://mirror.gravit.pro/5.2.x/", "https://mirror.gravit.pro/5.3.x/", "https://mirror.gravitlauncher.com/5.2.x/", "https://mirror.gravitlauncher.com/5.3.x/");
private transient final Logger logger = LogManager.getLogger(); private transient final Logger logger = LogManager.getLogger();
public String projectName; public String projectName;
public String[] mirrors; public String[] mirrors;
@ -46,7 +45,7 @@ public final class LaunchServerConfig {
public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) { public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
LaunchServerConfig newConfig = new LaunchServerConfig(); LaunchServerConfig newConfig = new LaunchServerConfig();
newConfig.mirrors = new String[]{"https://mirror.gravitlauncher.com/5.4.x/", "https://gravit-launcher-mirror.storage.googleapis.com/"}; newConfig.mirrors = new String[]{"https://mirror.gravitlauncher.com/5.3.x/", "https://gravit-launcher-mirror.storage.googleapis.com/"};
newConfig.launch4j = new LaunchServerConfig.ExeConf(); newConfig.launch4j = new LaunchServerConfig.ExeConf();
newConfig.launch4j.enabled = false; newConfig.launch4j.enabled = false;
newConfig.launch4j.copyright = "© GravitLauncher Team"; newConfig.launch4j.copyright = "© GravitLauncher Team";
@ -85,6 +84,7 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
newConfig.netty.performance.schedulerThread = 2; newConfig.netty.performance.schedulerThread = 2;
newConfig.launcher = new LauncherConf(); newConfig.launcher = new LauncherConf();
newConfig.launcher.guardType = "no";
newConfig.launcher.compress = true; newConfig.launcher.compress = true;
newConfig.launcher.deleteTempFiles = true; newConfig.launcher.deleteTempFiles = true;
newConfig.launcher.stripLineNumbers = true; newConfig.launcher.stripLineNumbers = true;
@ -107,8 +107,9 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
return newConfig; return newConfig;
} }
public void setLaunchServer(LaunchServer server) { public LaunchServerConfig setLaunchServer(LaunchServer server) {
this.server = server; this.server = server;
return this;
} }
public AuthProviderPair getAuthProviderPair(String name) { public AuthProviderPair getAuthProviderPair(String name) {
@ -167,9 +168,12 @@ public void verify() {
boolean updateMirror = Boolean.getBoolean("launchserver.config.disableUpdateMirror"); boolean updateMirror = Boolean.getBoolean("launchserver.config.disableUpdateMirror");
if (!updateMirror) { if (!updateMirror) {
for (int i = 0; i < mirrors.length; ++i) { for (int i = 0; i < mirrors.length; ++i) {
if (mirrors[i] != null && oldMirrorList.contains(mirrors[i])) { if ("https://mirror.gravit.pro/5.2.x/".equals(mirrors[i])) {
logger.warn("Replace mirror '{}' to 'https://mirror.gravitlauncher.com/5.4.x/'. If you really need to use original url, use '-Dlaunchserver.config.disableUpdateMirror=true'", mirrors[i]); logger.warn("Replace mirror 'https://mirror.gravit.pro/5.2.x/' to 'https://mirror.gravitlauncher.com/5.3.x/'. If you really need to use original url, use '-Dlaunchserver.config.disableUpdateMirror=true'");
mirrors[i] = "https://mirror.gravitlauncher.com/5.4.x/"; mirrors[i] = "https://mirror.gravitlauncher.com/5.3.x/";
} else if ("https://mirror.gravit.pro/5.3.x/".equals(mirrors[i])) {
logger.warn("Replace mirror 'https://mirror.gravit.pro/5.3.x/' to 'https://mirror.gravitlauncher.com/5.3.x/'. If you really need to use original url, use '-Dlaunchserver.config.disableUpdateMirror=true'");
mirrors[i] = "https://mirror.gravitlauncher.com/5.3.x/";
} }
} }
} }
@ -184,6 +188,7 @@ public void init(LaunchServer.ReloadType type) {
if (protectHandler != null) { if (protectHandler != null) {
server.registerObject("protectHandler", protectHandler); server.registerObject("protectHandler", protectHandler);
protectHandler.init(server); protectHandler.init(server);
protectHandler.checkLaunchServerLicense();
} }
if (components != null) { if (components != null) {
components.forEach((k, v) -> server.registerObject("component.".concat(k), v)); components.forEach((k, v) -> server.registerObject("component.".concat(k), v));
@ -264,6 +269,7 @@ public static class NettyUpdatesBind {
} }
public static class LauncherConf { public static class LauncherConf {
public String guardType;
public boolean compress; public boolean compress;
public boolean stripLineNumbers; public boolean stripLineNumbers;
public boolean deleteTempFiles; public boolean deleteTempFiles;

View file

@ -11,7 +11,6 @@ public class LaunchServerRuntimeConfig {
public String unlockSecret; public String unlockSecret;
public String registerApiKey; public String registerApiKey;
public String clientCheckSecret; public String clientCheckSecret;
public long buildNumber;
public void verify() { public void verify() {
if (passwordEncryptKey == null) logger.error("[RuntimeConfig] passwordEncryptKey must not be null"); if (passwordEncryptKey == null) logger.error("[RuntimeConfig] passwordEncryptKey must not be null");
@ -26,6 +25,5 @@ public void reset() {
runtimeEncryptKey = SecurityHelper.randomStringAESKey(); runtimeEncryptKey = SecurityHelper.randomStringAESKey();
registerApiKey = SecurityHelper.randomStringToken(); registerApiKey = SecurityHelper.randomStringToken();
clientCheckSecret = SecurityHelper.randomStringToken(); clientCheckSecret = SecurityHelper.randomStringToken();
buildNumber = 0;
} }
} }

View file

@ -22,7 +22,7 @@
import java.util.function.Function; import java.util.function.Function;
public final class HttpHelper { public final class HttpHelper {
private static final Logger logger = LogManager.getLogger(); private static transient final Logger logger = LogManager.getLogger();
private HttpHelper() { private HttpHelper() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
@ -37,7 +37,7 @@ public static <T, E> HttpOptional<T, E> send(HttpClient client, HttpRequest requ
} }
} }
public static <T, E> CompletableFuture<HttpOptional<T, E>> sendAsync(HttpClient client, HttpRequest request, HttpErrorHandler<T, E> handler) { public static <T, E> CompletableFuture<HttpOptional<T, E>> sendAsync(HttpClient client, HttpRequest request, HttpErrorHandler<T, E> handler) throws IOException {
return client.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()).thenApply(handler::apply); return client.sendAsync(request, HttpResponse.BodyHandlers.ofInputStream()).thenApply(handler::apply);
} }

View file

@ -2,7 +2,6 @@
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launcher.profiles.ClientProfileBuilder; import pro.gravit.launcher.profiles.ClientProfileBuilder;
import pro.gravit.launcher.profiles.ClientProfileVersions;
import pro.gravit.launcher.profiles.optional.OptionalFile; import pro.gravit.launcher.profiles.optional.OptionalFile;
import pro.gravit.launcher.profiles.optional.actions.OptionalActionFile; import pro.gravit.launcher.profiles.optional.actions.OptionalActionFile;
import pro.gravit.launcher.profiles.optional.actions.OptionalActionJvmArgs; import pro.gravit.launcher.profiles.optional.actions.OptionalActionJvmArgs;
@ -17,14 +16,14 @@
public class MakeProfileHelper { public class MakeProfileHelper {
public static ClientProfile makeProfile(ClientProfile.Version version, String title, MakeProfileOption... options) { public static ClientProfile makeProfile(ClientProfile.Version version, String title, MakeProfileOption... options) {
ClientProfileBuilder builder = new ClientProfileBuilder(); ClientProfileBuilder builder = new ClientProfileBuilder();
builder.setVersion(version); builder.setVersion(version.name);
builder.setDir(title); builder.setDir(title);
if (findOption(options, MakeProfileOptionGlobalAssets.class).isPresent()) { if (findOption(options, MakeProfileOptionGlobalAssets.class).isPresent()) {
builder.setAssetDir("assets"); builder.setAssetDir("assets");
} else { } else {
builder.setAssetDir("asset" + version.toCleanString()); builder.setAssetDir("asset" + version.name);
} }
builder.setAssetIndex(version.toString()); builder.setAssetIndex(version.name);
builder.setInfo("Информация о сервере"); builder.setInfo("Информация о сервере");
builder.setTitle(title); builder.setTitle(title);
builder.setUuid(UUID.randomUUID()); builder.setUuid(UUID.randomUUID());
@ -36,7 +35,7 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
List<String> classPath = new ArrayList<>(5); List<String> classPath = new ArrayList<>(5);
classPath.add("libraries"); classPath.add("libraries");
classPath.add("minecraft.jar"); classPath.add("minecraft.jar");
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) <= 0) { if (version.compareTo(ClientProfile.Version.MC1122) <= 0) {
findOption(options, MakeProfileOptionForge.class).ifPresent(e -> classPath.add("forge.jar")); findOption(options, MakeProfileOptionForge.class).ifPresent(e -> classPath.add("forge.jar"));
findOption(options, MakeProfileOptionLiteLoader.class).ifPresent(e -> classPath.add("liteloader.jar")); findOption(options, MakeProfileOptionLiteLoader.class).ifPresent(e -> classPath.add("liteloader.jar"));
} }
@ -47,21 +46,20 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
Set<OptionalFile> optionals = new HashSet<>(); Set<OptionalFile> optionals = new HashSet<>();
jvmArgs.add("-XX:+DisableAttachMechanism"); jvmArgs.add("-XX:+DisableAttachMechanism");
// Official Mojang launcher java arguments // Official Mojang launcher java arguments
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) <= 0) { if (version.compareTo(ClientProfile.Version.MC112) <= 0) {
jvmArgs.add("-XX:+UseConcMarkSweepGC"); jvmArgs.add("-XX:+UseConcMarkSweepGC");
jvmArgs.add("-XX:+CMSIncrementalMode"); jvmArgs.add("-XX:+CMSIncrementalMode");
} else if (version.compareTo(ClientProfileVersions.MINECRAFT_1_18) <= 0) { // 1.13 - 1.16.5 } else if (version.compareTo(ClientProfile.Version.MC118) <= 0) { // 1.13 - 1.16.5
jvmArgs.add("-XX:+UseG1GC"); jvmArgs.add("-XX:+UseG1GC");
jvmArgs.add("-XX:+UnlockExperimentalVMOptions"); jvmArgs.add("-XX:+UnlockExperimentalVMOptions");
} else { // 1.18+ } else { // 1.18+
//jvmArgs.add("-XX:+UseShenandoahGC"); jvmArgs.add("-XX:+UseShenandoahGC");
//jvmArgs.add("-XX:+UnlockExperimentalVMOptions"); jvmArgs.add("-XX:+UnlockExperimentalVMOptions");
} }
// ----------- // -----------
Optional<MakeProfileOptionForge> forge = findOption(options, MakeProfileOptionForge.class); Optional<MakeProfileOptionForge> forge = findOption(options, MakeProfileOptionForge.class);
Optional<MakeProfileOptionFabric> fabric = findOption(options, MakeProfileOptionFabric.class); Optional<MakeProfileOptionFabric> fabric = findOption(options, MakeProfileOptionFabric.class);
Optional<MakeProfilesOptionsQuilt> quilt = findOption(options, MakeProfilesOptionsQuilt.class); if (version.compareTo(ClientProfile.Version.MC1122) > 0) {
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) > 0) {
jvmArgs.add("-Djava.library.path=natives"); jvmArgs.add("-Djava.library.path=natives");
OptionalFile optionalMacOs = new OptionalFile(); OptionalFile optionalMacOs = new OptionalFile();
optionalMacOs.name = "MacOSArgs"; optionalMacOs.name = "MacOSArgs";
@ -74,9 +72,6 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
if (fabric.isPresent()) { if (fabric.isPresent()) {
builder.setAltClassPath(fabric.orElseThrow().getAltClassPath()); builder.setAltClassPath(fabric.orElseThrow().getAltClassPath());
} }
if(quilt.isPresent()) {
builder.setClassLoaderConfig(ClientProfile.ClassLoaderConfig.SYSTEM_ARGS);
}
if (findOption(options, MakeProfileOptionLwjgl.class).isPresent()) { if (findOption(options, MakeProfileOptionLwjgl.class).isPresent()) {
OptionalFile optionalMac = new OptionalFile(); OptionalFile optionalMac = new OptionalFile();
optionalMac.name = "MacLwjgl"; optionalMac.name = "MacLwjgl";
@ -117,16 +112,16 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
if (log4jOption.logFile != null) { if (log4jOption.logFile != null) {
jvmArgs.add("-Dlog4j.configurationFile=".concat(logFile.get().logFile)); jvmArgs.add("-Dlog4j.configurationFile=".concat(logFile.get().logFile));
} else if (log4jOption.affected) { } else if (log4jOption.affected) {
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_17) >= 0 && version.compareTo(ClientProfileVersions.MINECRAFT_1_18) < 0) { if (version.compareTo(ClientProfile.Version.MC117) >= 0 && version.compareTo(ClientProfile.Version.MC118) < 0) {
jvmArgs.add("-Dlog4j2.formatMsgNoLookups=true"); jvmArgs.add("-Dlog4j2.formatMsgNoLookups=true");
} }
} }
} }
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_17) >= 0 && version.compareTo(ClientProfileVersions.MINECRAFT_1_18) < 0) { if (version.compareTo(ClientProfile.Version.MC117) >= 0 && version.compareTo(ClientProfile.Version.MC118) < 0) {
builder.setMinJavaVersion(16); builder.setMinJavaVersion(16);
builder.setRecommendJavaVersion(16); builder.setRecommendJavaVersion(16);
} }
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_18) >= 0) { if (version.compareTo(ClientProfile.Version.MC118) >= 0) {
builder.setMinJavaVersion(17); builder.setMinJavaVersion(17);
builder.setRecommendJavaVersion(17); builder.setRecommendJavaVersion(17);
} }
@ -142,22 +137,22 @@ public static ClientProfile makeProfile(ClientProfile.Version version, String ti
} }
if (forge.isPresent()) { if (forge.isPresent()) {
clientArgs.add("--tweakClass"); clientArgs.add("--tweakClass");
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_10) > 0) { if (version.compareTo(ClientProfile.Version.MC1710) > 0) {
clientArgs.add("net.minecraftforge.fml.common.launcher.FMLTweaker"); clientArgs.add("net.minecraftforge.fml.common.launcher.FMLTweaker");
} else { } else {
clientArgs.add("cpw.mods.fml.common.launcher.FMLTweaker"); clientArgs.add("cpw.mods.fml.common.launcher.FMLTweaker");
} }
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) <= 0) { if (version.compareTo(ClientProfile.Version.MC1122) <= 0) {
builder.setMinJavaVersion(8); builder.setMinJavaVersion(8);
builder.setRecommendJavaVersion(8); builder.setRecommendJavaVersion(8);
builder.setMaxJavaVersion(8); builder.setMaxJavaVersion(8);
} }
} }
} else if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) > 0) { } else if (version.compareTo(ClientProfile.Version.MC1122) > 0) {
if (forge.isPresent()) { if (forge.isPresent()) {
clientArgs.addAll(forge.get().makeClientArgs()); clientArgs.addAll(forge.get().makeClientArgs());
builder.setClassLoaderConfig(ClientProfile.ClassLoaderConfig.SYSTEM_ARGS); builder.setClassLoaderConfig(ClientProfile.ClassLoaderConfig.AGENT);
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_16_5) <= 0) { if (version.compareTo(ClientProfile.Version.MC1165) <= 0) {
builder.setMaxJavaVersion(15); builder.setMaxJavaVersion(15);
} }
} }
@ -176,15 +171,12 @@ public static String getMainClassByVersion(ClientProfile.Version version, MakePr
if (findOption(options, MakeProfileOptionLaunchWrapper.class).isPresent()) { if (findOption(options, MakeProfileOptionLaunchWrapper.class).isPresent()) {
return "net.minecraft.launchwrapper.Launch"; return "net.minecraft.launchwrapper.Launch";
} }
if (findOption(options, MakeProfileOptionForge.class).isPresent() && version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) > 0) { if (findOption(options, MakeProfileOptionForge.class).isPresent() && version.compareTo(ClientProfile.Version.MC1122) > 0) {
return "cpw.mods.modlauncher.Launcher"; return "cpw.mods.modlauncher.Launcher";
} }
if (findOption(options, MakeProfileOptionFabric.class).isPresent()) { if (findOption(options, MakeProfileOptionFabric.class).isPresent()) {
return "net.fabricmc.loader.launch.knot.KnotClient"; return "net.fabricmc.loader.launch.knot.KnotClient";
} }
if(findOption(options, MakeProfilesOptionsQuilt.class).isPresent()) {
return "org.quiltmc.loader.impl.launch.knot.KnotClient";
}
return "net.minecraft.client.main.Main"; return "net.minecraft.client.main.Main";
} }
@ -214,7 +206,7 @@ public static MakeProfileOption[] getMakeProfileOptionsFromDir(Path dir, ClientP
if (Files.exists(dir.resolve("forge.jar"))) { if (Files.exists(dir.resolve("forge.jar"))) {
options.add(new MakeProfileOptionForge()); options.add(new MakeProfileOptionForge());
} else if (Files.exists(dir.resolve("libraries/net/minecraftforge/forge"))) { } else if (Files.exists(dir.resolve("libraries/net/minecraftforge/forge"))) {
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_12_2) > 0) { if (version.compareTo(ClientProfile.Version.MC1122) > 0) {
options.add(new MakeProfileOptionForge(dir)); options.add(new MakeProfileOptionForge(dir));
} else { } else {
options.add(new MakeProfileOptionForge()); options.add(new MakeProfileOptionForge());
@ -223,9 +215,6 @@ public static MakeProfileOption[] getMakeProfileOptionsFromDir(Path dir, ClientP
if (Files.exists(dir.resolve("libraries/net/fabricmc/fabric-loader"))) { if (Files.exists(dir.resolve("libraries/net/fabricmc/fabric-loader"))) {
options.add(new MakeProfileOptionFabric(dir)); options.add(new MakeProfileOptionFabric(dir));
} }
if (Files.exists(dir.resolve("libraries/org/quiltmc/quilt-loader"))) {
options.add(new MakeProfilesOptionsQuilt());
}
{ {
String log4jVersion = getLog4jVersion(dir); String log4jVersion = getLog4jVersion(dir);
if (log4jVersion != null) { if (log4jVersion != null) {
@ -354,10 +343,6 @@ public List<String> getAltClassPath() {
} }
} }
public static class MakeProfilesOptionsQuilt implements MakeProfileOption {
}
public static class MakeProfileOptionLiteLoader implements MakeProfileOption { public static class MakeProfileOptionLiteLoader implements MakeProfileOption {
} }

View file

@ -119,6 +119,17 @@ public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IO
ModuleEntity entity = new ModuleEntity(); ModuleEntity entity = new ModuleEntity();
entity.path = file; entity.path = file;
entity.moduleMainClass = mainClass; entity.moduleMainClass = mainClass;
try {
Class<? extends LauncherModule> mainClazz = (Class<? extends LauncherModule>) classLoader.loadClass(entity.moduleMainClass);
entity.checkResult = server.modulesManager.checkModuleClass(mainClazz);
} catch (Throwable e) {
if (e instanceof ClassNotFoundException || e instanceof NoClassDefFoundError) {
logger.error("Module-MainClass in module {} incorrect", file.toString());
} else {
logger.error(e);
}
return super.visitFile(file, attrs);
}
entity.moduleConfigClass = attributes.getValue("Module-Config-Class"); entity.moduleConfigClass = attributes.getValue("Module-Config-Class");
if (entity.moduleConfigClass != null) { if (entity.moduleConfigClass != null) {
entity.moduleConfigName = attributes.getValue("Module-Config-Name"); entity.moduleConfigName = attributes.getValue("Module-Config-Name");

View file

@ -7,9 +7,11 @@
import java.util.Map; import java.util.Map;
public class FeaturesManager { public class FeaturesManager {
private final transient LaunchServer server;
private final Map<String, String> map; private final Map<String, String> map;
public FeaturesManager(LaunchServer server) { public FeaturesManager(LaunchServer server) {
this.server = server;
map = new HashMap<>(); map = new HashMap<>();
addFeatureInfo("version", Version.getVersion().getVersionString()); addFeatureInfo("version", Version.getVersion().getVersionString());
addFeatureInfo("projectName", server.config.projectName); addFeatureInfo("projectName", server.config.projectName);
@ -23,8 +25,8 @@ public String getFeatureInfo(String name) {
return map.get(name); return map.get(name);
} }
public void addFeatureInfo(String name, String featureInfo) { public String addFeatureInfo(String name, String featureInfo) {
map.put(name, featureInfo); return map.put(name, featureInfo);
} }
public String removeFeatureInfo(String name) { public String removeFeatureInfo(String name) {

View file

@ -22,6 +22,7 @@ public class KeyAgreementManager {
public final RSAPublicKey rsaPublicKey; public final RSAPublicKey rsaPublicKey;
public final RSAPrivateKey rsaPrivateKey; public final RSAPrivateKey rsaPrivateKey;
public final String legacySalt; public final String legacySalt;
private transient final Logger logger = LogManager.getLogger();
public KeyAgreementManager(ECPublicKey ecdsaPublicKey, ECPrivateKey ecdsaPrivateKey, RSAPublicKey rsaPublicKey, RSAPrivateKey rsaPrivateKey, String legacySalt) { public KeyAgreementManager(ECPublicKey ecdsaPublicKey, ECPrivateKey ecdsaPrivateKey, RSAPublicKey rsaPublicKey, RSAPrivateKey rsaPrivateKey, String legacySalt) {
this.ecdsaPublicKey = ecdsaPublicKey; this.ecdsaPublicKey = ecdsaPublicKey;
@ -33,7 +34,6 @@ public KeyAgreementManager(ECPublicKey ecdsaPublicKey, ECPrivateKey ecdsaPrivate
public KeyAgreementManager(Path keyDirectory) throws IOException, InvalidKeySpecException { public KeyAgreementManager(Path keyDirectory) throws IOException, InvalidKeySpecException {
Path ecdsaPublicKeyPath = keyDirectory.resolve("ecdsa_id.pub"), ecdsaPrivateKeyPath = keyDirectory.resolve("ecdsa_id"); Path ecdsaPublicKeyPath = keyDirectory.resolve("ecdsa_id.pub"), ecdsaPrivateKeyPath = keyDirectory.resolve("ecdsa_id");
Logger logger = LogManager.getLogger();
if (IOHelper.isFile(ecdsaPublicKeyPath) && IOHelper.isFile(ecdsaPrivateKeyPath)) { if (IOHelper.isFile(ecdsaPublicKeyPath) && IOHelper.isFile(ecdsaPrivateKeyPath)) {
logger.info("Reading ECDSA keypair"); logger.info("Reading ECDSA keypair");
ecdsaPublicKey = SecurityHelper.toPublicECDSAKey(IOHelper.read(ecdsaPublicKeyPath)); ecdsaPublicKey = SecurityHelper.toPublicECDSAKey(IOHelper.read(ecdsaPublicKeyPath));

View file

@ -5,7 +5,6 @@
import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent; import pro.gravit.launcher.events.request.GetAvailabilityAuthRequestEvent;
import pro.gravit.launcher.managers.GsonManager; import pro.gravit.launcher.managers.GsonManager;
import pro.gravit.launcher.modules.events.PreGsonPhase; import pro.gravit.launcher.modules.events.PreGsonPhase;
import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launcher.profiles.optional.actions.OptionalAction; import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger; import pro.gravit.launcher.profiles.optional.triggers.OptionalTrigger;
import pro.gravit.launcher.request.JsonResultSerializeAdapter; import pro.gravit.launcher.request.JsonResultSerializeAdapter;
@ -36,7 +35,6 @@ public void registerAdapters(GsonBuilder builder) {
builder.registerTypeAdapterFactory(RecordTypeAdapterFactory.builder() builder.registerTypeAdapterFactory(RecordTypeAdapterFactory.builder()
.allowMissingComponentValues() .allowMissingComponentValues()
.create()); .create());
builder.registerTypeAdapter(ClientProfile.Version.class, new ClientProfile.Version.GsonSerializer());
builder.registerTypeAdapter(TextureProvider.class, new UniversalJsonAdapter<>(TextureProvider.providers)); builder.registerTypeAdapter(TextureProvider.class, new UniversalJsonAdapter<>(TextureProvider.providers));
builder.registerTypeAdapter(AuthCoreProvider.class, new UniversalJsonAdapter<>(AuthCoreProvider.providers)); builder.registerTypeAdapter(AuthCoreProvider.class, new UniversalJsonAdapter<>(AuthCoreProvider.providers));
builder.registerTypeAdapter(PasswordVerifier.class, new UniversalJsonAdapter<>(PasswordVerifier.providers)); builder.registerTypeAdapter(PasswordVerifier.class, new UniversalJsonAdapter<>(PasswordVerifier.providers));

View file

@ -1,12 +0,0 @@
package pro.gravit.launchserver.modules.events;
import pro.gravit.launcher.modules.LauncherModule;
import pro.gravit.launchserver.LaunchServer;
public class LaunchServerNettyFullInitEvent extends LauncherModule.Event {
public final LaunchServer server;
public LaunchServerNettyFullInitEvent(LaunchServer server) {
this.server = server;
}
}

View file

@ -1,6 +1,7 @@
package pro.gravit.launchserver.socket; package pro.gravit.launchserver.socket;
import io.netty.bootstrap.ServerBootstrap; import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline; import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup; import io.netty.channel.EventLoopGroup;
@ -33,11 +34,11 @@ public class LauncherNettyServer implements AutoCloseable {
public final EventLoopGroup workerGroup; public final EventLoopGroup workerGroup;
public final WebSocketService service; public final WebSocketService service;
public final BiHookSet<NettyConnectContext, SocketChannel> pipelineHook = new BiHookSet<>(); public final BiHookSet<NettyConnectContext, SocketChannel> pipelineHook = new BiHookSet<>();
private transient final Logger logger = LogManager.getLogger();
public LauncherNettyServer(LaunchServer server) { public LauncherNettyServer(LaunchServer server) {
LaunchServerConfig.NettyConfig config = server.config.netty; LaunchServerConfig.NettyConfig config = server.config.netty;
NettyObjectFactory.setUsingEpoll(config.performance.usingEpoll); NettyObjectFactory.setUsingEpoll(config.performance.usingEpoll);
Logger logger = LogManager.getLogger();
if (config.performance.usingEpoll) { if (config.performance.usingEpoll) {
logger.debug("Netty: Epoll enabled"); logger.debug("Netty: Epoll enabled");
} }
@ -73,8 +74,8 @@ public void initChannel(SocketChannel ch) {
}); });
} }
public void bind(InetSocketAddress address) { public ChannelFuture bind(InetSocketAddress address) {
serverBootstrap.bind(address); return serverBootstrap.bind(address);
} }
@Override @Override

View file

@ -5,6 +5,7 @@
import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.ChannelMatchers;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -20,6 +21,7 @@
import pro.gravit.launchserver.socket.response.auth.*; import pro.gravit.launchserver.socket.response.auth.*;
import pro.gravit.launchserver.socket.response.management.FeaturesResponse; import pro.gravit.launchserver.socket.response.management.FeaturesResponse;
import pro.gravit.launchserver.socket.response.management.GetPublicKeyResponse; import pro.gravit.launchserver.socket.response.management.GetPublicKeyResponse;
import pro.gravit.launchserver.socket.response.management.ServerStatusResponse;
import pro.gravit.launchserver.socket.response.profile.BatchProfileByUsername; import pro.gravit.launchserver.socket.response.profile.BatchProfileByUsername;
import pro.gravit.launchserver.socket.response.profile.ProfileByUUIDResponse; import pro.gravit.launchserver.socket.response.profile.ProfileByUUIDResponse;
import pro.gravit.launchserver.socket.response.profile.ProfileByUsername; import pro.gravit.launchserver.socket.response.profile.ProfileByUsername;
@ -31,21 +33,26 @@
import pro.gravit.launchserver.socket.response.update.UpdateListResponse; import pro.gravit.launchserver.socket.response.update.UpdateListResponse;
import pro.gravit.launchserver.socket.response.update.UpdateResponse; import pro.gravit.launchserver.socket.response.update.UpdateResponse;
import pro.gravit.utils.BiHookSet; import pro.gravit.utils.BiHookSet;
import pro.gravit.utils.HookSet;
import pro.gravit.utils.ProviderMap; import pro.gravit.utils.ProviderMap;
import pro.gravit.utils.helper.IOHelper; import pro.gravit.utils.helper.IOHelper;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.UUID; import java.util.UUID;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
public class WebSocketService { public class WebSocketService {
public static final ProviderMap<WebSocketServerResponse> providers = new ProviderMap<>(); public static final ProviderMap<WebSocketServerResponse> providers = new ProviderMap<>();
public final ChannelGroup channels; public final ChannelGroup channels;
public final HookSet<WebSocketRequestContext> hookBeforeParsing = new HookSet<>(); public final BiHookSet<WebSocketRequestContext, ChannelHandlerContext> hook = new BiHookSet<>();
public final HookSet<WebSocketRequestContext> hookBeforeExecute = new HookSet<>(); //Statistic data
public final HookSet<WebSocketRequestContext> hookComplete = new HookSet<>(); public final AtomicLong shortRequestLatency = new AtomicLong();
public final BiHookSet<Channel, Object> hookSend = new BiHookSet<>(); public final AtomicLong shortRequestCounter = new AtomicLong();
public final AtomicLong middleRequestLatency = new AtomicLong();
public final AtomicLong middleRequestCounter = new AtomicLong();
public final AtomicLong longRequestLatency = new AtomicLong();
public final AtomicLong longRequestCounter = new AtomicLong();
public final AtomicLong lastRequestTime = new AtomicLong();
private final LaunchServer server; private final LaunchServer server;
private final Gson gson; private final Gson gson;
private transient final Logger logger = LogManager.getLogger(); private transient final Logger logger = LogManager.getLogger();
@ -56,6 +63,7 @@ public WebSocketService(ChannelGroup channels, LaunchServer server) {
this.gson = Launcher.gsonManager.gson; this.gson = Launcher.gsonManager.gson;
} }
@SuppressWarnings("deprecation")
public static void registerResponses() { public static void registerResponses() {
providers.register("auth", AuthResponse.class); providers.register("auth", AuthResponse.class);
providers.register("checkServer", CheckServerResponse.class); providers.register("checkServer", CheckServerResponse.class);
@ -75,6 +83,7 @@ public static void registerResponses() {
providers.register("verifySecureLevelKey", VerifySecureLevelKeyResponse.class); providers.register("verifySecureLevelKey", VerifySecureLevelKeyResponse.class);
providers.register("securityReport", SecurityReportResponse.class); providers.register("securityReport", SecurityReportResponse.class);
providers.register("hardwareReport", HardwareReportResponse.class); providers.register("hardwareReport", HardwareReportResponse.class);
providers.register("serverStatus", ServerStatusResponse.class);
providers.register("currentUser", CurrentUserResponse.class); providers.register("currentUser", CurrentUserResponse.class);
providers.register("features", FeaturesResponse.class); providers.register("features", FeaturesResponse.class);
providers.register("refreshToken", RefreshTokenResponse.class); providers.register("refreshToken", RefreshTokenResponse.class);
@ -110,27 +119,55 @@ public void forEachActiveChannels(BiConsumer<Channel, WebSocketFrameHandler> cal
} }
public void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) { public void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) {
long startTimeNanos = System.nanoTime();
String request = frame.text(); String request = frame.text();
WebSocketRequestContext context = new WebSocketRequestContext(ctx, request, client, ip);
if(hookBeforeParsing.hook(context)) {
return;
}
WebSocketServerResponse response = gson.fromJson(request, WebSocketServerResponse.class); WebSocketServerResponse response = gson.fromJson(request, WebSocketServerResponse.class);
context.response = response;
if (response == null) { if (response == null) {
RequestEvent event = new ErrorRequestEvent("This type of request is not supported"); RequestEvent event = new ErrorRequestEvent("This type of request is not supported");
hookComplete.hook(context); sendObject(ctx, event);
sendObject(ctx.channel(), event, WebSocketEvent.class);
return; return;
} }
process(context, response, client, ip); process(ctx, response, client, ip);
long executeTime = System.nanoTime() - startTimeNanos;
if (executeTime > 0) {
addRequestTimeToStats(executeTime);
}
} }
void process(WebSocketRequestContext context, WebSocketServerResponse response, Client client, String ip) { public void addRequestTimeToStats(long nanos) {
if (hookBeforeExecute.hook(context)) { if (nanos < 100_000_000L) // < 100 millis
{
shortRequestCounter.getAndIncrement();
shortRequestLatency.getAndAdd(nanos);
} else if (nanos < 1_000_000_000L) // > 100 millis and < 1 second
{
middleRequestCounter.getAndIncrement();
middleRequestLatency.getAndAdd(nanos);
} else // > 1 second
{
longRequestCounter.getAndIncrement();
longRequestLatency.getAndAdd(nanos);
}
long lastTime = lastRequestTime.get();
long currentTime = System.currentTimeMillis();
if (currentTime - lastTime > 60 * 1000) //1 minute
{
lastRequestTime.set(currentTime);
shortRequestLatency.set(0);
shortRequestCounter.set(0);
middleRequestCounter.set(0);
middleRequestLatency.set(0);
longRequestCounter.set(0);
longRequestLatency.set(0);
}
}
void process(ChannelHandlerContext ctx, WebSocketServerResponse response, Client client, String ip) {
WebSocketRequestContext context = new WebSocketRequestContext(response, client, ip);
if (hook.hook(context, ctx)) {
return; return;
} }
ChannelHandlerContext ctx = context.context;
if (response instanceof SimpleResponse simpleResponse) { if (response instanceof SimpleResponse simpleResponse) {
simpleResponse.server = server; simpleResponse.server = server;
simpleResponse.service = this; simpleResponse.service = this;
@ -140,27 +177,38 @@ void process(WebSocketRequestContext context, WebSocketServerResponse response,
} }
try { try {
response.execute(ctx, client); response.execute(ctx, client);
} catch (Throwable e) { } catch (Exception e) {
context.exception = e;
logger.error("WebSocket request processing failed", e); logger.error("WebSocket request processing failed", e);
RequestEvent event; RequestEvent event;
event = new ErrorRequestEvent("Fatal server error. Contact administrator"); event = new ErrorRequestEvent("Fatal server error. Contact administrator");
if (response instanceof SimpleResponse) { if (response instanceof SimpleResponse) {
event.requestUUID = ((SimpleResponse) response).requestUUID; event.requestUUID = ((SimpleResponse) response).requestUUID;
} }
sendObject(ctx.channel(), event); sendObject(ctx, event);
} }
hookComplete.hook(context);
} }
public void registerClient(Channel channel) { public void registerClient(Channel channel) {
channels.add(channel); channels.add(channel);
} }
public void sendObject(Channel channel, Object obj) { public void sendObject(ChannelHandlerContext ctx, Object obj) {
if(hookSend.hook(channel, obj)) { String msg = gson.toJson(obj, WebSocketEvent.class);
return; if (logger.isTraceEnabled()) {
logger.trace("Send to {}: {}", getIPFromContext(ctx), msg);
} }
ctx.writeAndFlush(new TextWebSocketFrame(msg), ctx.voidPromise());
}
public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) {
String msg = gson.toJson(obj, type);
if (logger.isTraceEnabled()) {
logger.trace("Send to {}: {}", getIPFromContext(ctx), msg);
}
ctx.writeAndFlush(new TextWebSocketFrame(msg), ctx.voidPromise());
}
public void sendObject(Channel channel, Object obj) {
String msg = gson.toJson(obj, WebSocketEvent.class); String msg = gson.toJson(obj, WebSocketEvent.class);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Send to channel {}: {}", getIPFromChannel(channel), msg); logger.trace("Send to channel {}: {}", getIPFromChannel(channel), msg);
@ -169,9 +217,6 @@ public void sendObject(Channel channel, Object obj) {
} }
public void sendObject(Channel channel, Object obj, Type type) { public void sendObject(Channel channel, Object obj, Type type) {
if(hookSend.hook(channel, obj)) {
return;
}
String msg = gson.toJson(obj, type); String msg = gson.toJson(obj, type);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Send to channel {}: {}", getIPFromChannel(channel), msg); logger.trace("Send to channel {}: {}", getIPFromChannel(channel), msg);
@ -179,9 +224,23 @@ public void sendObject(Channel channel, Object obj, Type type) {
channel.writeAndFlush(new TextWebSocketFrame(msg), channel.voidPromise()); channel.writeAndFlush(new TextWebSocketFrame(msg), channel.voidPromise());
} }
public void sendObjectAll(Object obj, Type type) { public void sendObjectAll(Object obj) {
String msg = gson.toJson(obj, WebSocketEvent.class);
if (logger.isTraceEnabled()) {
logger.trace("Send to all: {}", msg);
}
for (Channel ch : channels) { for (Channel ch : channels) {
sendObject(ch, obj, type); ch.writeAndFlush(new TextWebSocketFrame(msg), ch.voidPromise());
}
}
public void sendObjectAll(Object obj, Type type) {
String msg = gson.toJson(obj, type);
if (logger.isTraceEnabled()) {
logger.trace("Send to all: {}", msg);
}
for (Channel ch : channels) {
ch.writeAndFlush(new TextWebSocketFrame(msg), ch.voidPromise());
} }
} }
@ -192,9 +251,6 @@ public void sendObjectToUUID(UUID userUuid, Object obj, Type type) {
if (wsHandler == null) continue; if (wsHandler == null) continue;
Client client = wsHandler.getClient(); Client client = wsHandler.getClient();
if (client == null || !userUuid.equals(client.uuid)) continue; if (client == null || !userUuid.equals(client.uuid)) continue;
if(hookSend.hook(ch, obj)) {
continue;
}
String msg = gson.toJson(obj, type); String msg = gson.toJson(obj, type);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Send to {}({}): {}", getIPFromChannel(ch), userUuid, msg); logger.trace("Send to {}({}): {}", getIPFromChannel(ch), userUuid, msg);
@ -263,9 +319,6 @@ public boolean kickByIP(String ip, boolean isClose) {
} }
public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj) { public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj) {
if(hookSend.hook(ctx.channel(), obj)) {
return;
}
String msg = gson.toJson(obj, WebSocketEvent.class); String msg = gson.toJson(obj, WebSocketEvent.class);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Send and close {}: {}", getIPFromContext(ctx), msg); logger.trace("Send and close {}: {}", getIPFromContext(ctx), msg);
@ -274,9 +327,6 @@ public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj) {
} }
public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type) { public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type) {
if(hookSend.hook(ctx.channel(), obj)) {
return;
}
String msg = gson.toJson(obj, type); String msg = gson.toJson(obj, type);
if (logger.isTraceEnabled()) { if (logger.isTraceEnabled()) {
logger.trace("Send and close {}: {}", getIPFromContext(ctx), msg); logger.trace("Send and close {}: {}", getIPFromContext(ctx), msg);
@ -284,17 +334,22 @@ public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type)
ctx.writeAndFlush(new TextWebSocketFrame(msg)).addListener(ChannelFutureListener.CLOSE); ctx.writeAndFlush(new TextWebSocketFrame(msg)).addListener(ChannelFutureListener.CLOSE);
} }
@Deprecated
public void sendEvent(EventResult obj) {
String msg = gson.toJson(obj, WebSocketEvent.class);
if (logger.isTraceEnabled()) {
logger.trace("Send event: {}", msg);
}
channels.writeAndFlush(new TextWebSocketFrame(msg), ChannelMatchers.all(), true);
}
public static class WebSocketRequestContext { public static class WebSocketRequestContext {
public final ChannelHandlerContext context; public final WebSocketServerResponse response;
public final String text;
public final Client client; public final Client client;
public final String ip; public final String ip;
public WebSocketServerResponse response;
public Throwable exception;
public WebSocketRequestContext(ChannelHandlerContext context, String text, Client client, String ip) { public WebSocketRequestContext(WebSocketServerResponse response, Client client, String ip) {
this.context = context; this.response = response;
this.text = text;
this.client = client; this.client = client;
this.ip = ip; this.ip = ip;
} }

View file

@ -4,7 +4,6 @@
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import pro.gravit.launchserver.LaunchServer; import pro.gravit.launchserver.LaunchServer;
import pro.gravit.launchserver.config.LaunchServerConfig; import pro.gravit.launchserver.config.LaunchServerConfig;
import pro.gravit.launchserver.modules.events.LaunchServerNettyFullInitEvent;
import pro.gravit.launchserver.socket.LauncherNettyServer; import pro.gravit.launchserver.socket.LauncherNettyServer;
import javax.net.ssl.SSLServerSocketFactory; import javax.net.ssl.SSLServerSocketFactory;
@ -35,6 +34,5 @@ public void run() {
for (LaunchServerConfig.NettyBindAddress address : server.config.netty.binds) { for (LaunchServerConfig.NettyBindAddress address : server.config.netty.binds) {
nettyServer.bind(new InetSocketAddress(address.address, address.port)); nettyServer.bind(new InetSocketAddress(address.address, address.port));
} }
server.modulesManager.invokeEvent(new LaunchServerNettyFullInitEvent(server));
} }
} }

View file

@ -36,9 +36,10 @@ public NettyWebAPIHandler(NettyConnectContext context) {
this.context = context; this.context = context;
} }
public static void addNewSeverlet(String path, SimpleSeverletHandler callback) { public static SeverletPathPair addNewSeverlet(String path, SimpleSeverletHandler callback) {
SeverletPathPair pair = new SeverletPathPair("/webapi/".concat(path), callback); SeverletPathPair pair = new SeverletPathPair("/webapi/".concat(path), callback);
severletList.add(pair); severletList.add(pair);
return pair;
} }
public static SeverletPathPair addUnsafeSeverlet(String path, SimpleSeverletHandler callback) { public static SeverletPathPair addUnsafeSeverlet(String path, SimpleSeverletHandler callback) {
@ -52,7 +53,7 @@ public static void removeSeverlet(SeverletPathPair pair) {
} }
@Override @Override
protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) { protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) throws Exception {
boolean isNext = true; boolean isNext = true;
for (SeverletPathPair pair : severletList) { for (SeverletPathPair pair : severletList) {
if (msg.uri().startsWith(pair.key)) { if (msg.uri().startsWith(pair.key)) {
@ -74,7 +75,7 @@ protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest msg) {
@FunctionalInterface @FunctionalInterface
public interface SimpleSeverletHandler { public interface SimpleSeverletHandler {
void handle(ChannelHandlerContext ctx, FullHttpRequest msg, NettyConnectContext context); void handle(ChannelHandlerContext ctx, FullHttpRequest msg, NettyConnectContext context) throws Exception;
default Map<String, String> getParamsFromUri(String uri) { default Map<String, String> getParamsFromUri(String uri) {
int ind = uri.indexOf("?"); int ind = uri.indexOf("?");

View file

@ -17,7 +17,7 @@ public abstract class SimpleResponse implements WebSocketServerResponse {
public void sendResult(RequestEvent result) { public void sendResult(RequestEvent result) {
result.requestUUID = requestUUID; result.requestUUID = requestUUID;
service.sendObject(ctx.channel(), result); service.sendObject(ctx, result);
} }
public void sendResultAndClose(RequestEvent result) { public void sendResultAndClose(RequestEvent result) {
@ -28,6 +28,6 @@ public void sendResultAndClose(RequestEvent result) {
public void sendError(String errorMessage) { public void sendError(String errorMessage) {
ErrorRequestEvent event = new ErrorRequestEvent(errorMessage); ErrorRequestEvent event = new ErrorRequestEvent(errorMessage);
event.requestUUID = requestUUID; event.requestUUID = requestUUID;
service.sendObject(ctx.channel(), event); service.sendObject(ctx, event);
} }
} }

View file

@ -11,6 +11,7 @@
import java.util.Map; import java.util.Map;
import java.util.UUID; import java.util.UUID;
@SuppressWarnings("deprecation")
public class AdditionalDataResponse extends SimpleResponse { public class AdditionalDataResponse extends SimpleResponse {
public String username; public String username;
public UUID uuid; public UUID uuid;
@ -21,7 +22,7 @@ public String getType() {
} }
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
if (!client.isAuth) { if (!client.isAuth) {
sendError("Access denied"); sendError("Access denied");
return; return;

View file

@ -28,7 +28,7 @@ public String getType() {
} }
@Override @Override
public void execute(ChannelHandlerContext ctx, Client clientData) { public void execute(ChannelHandlerContext ctx, Client clientData) throws Exception {
try { try {
AuthRequestEvent result = new AuthRequestEvent(); AuthRequestEvent result = new AuthRequestEvent();
AuthProviderPair pair; AuthProviderPair pair;

View file

@ -6,9 +6,11 @@
import pro.gravit.launchserver.socket.Client; import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.SimpleResponse; import pro.gravit.launchserver.socket.response.SimpleResponse;
import java.io.IOException;
public class CurrentUserResponse extends SimpleResponse { public class CurrentUserResponse extends SimpleResponse {
public static CurrentUserRequestEvent.UserInfo collectUserInfoFromClient(LaunchServer server, Client client) { public static CurrentUserRequestEvent.UserInfo collectUserInfoFromClient(LaunchServer server, Client client) throws IOException {
CurrentUserRequestEvent.UserInfo result = new CurrentUserRequestEvent.UserInfo(); CurrentUserRequestEvent.UserInfo result = new CurrentUserRequestEvent.UserInfo();
if (client.auth != null && client.isAuth && client.username != null) { if (client.auth != null && client.isAuth && client.username != null) {
result.playerProfile = server.authManager.getPlayerProfile(client); result.playerProfile = server.authManager.getPlayerProfile(client);

View file

@ -14,7 +14,7 @@ public String getType() {
} }
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
if (!client.isAuth || client.type != AuthResponse.ConnectTypes.CLIENT) { if (!client.isAuth || client.type != AuthResponse.ConnectTypes.CLIENT) {
sendError("Permissions denied"); sendError("Permissions denied");
return; return;

View file

@ -18,7 +18,7 @@ public String getType() {
} }
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
if (refreshToken == null) { if (refreshToken == null) {
sendError("Invalid request"); sendError("Invalid request");
return; return;

View file

@ -76,10 +76,6 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
return; return;
} }
User user = session.getUser(); User user = session.getUser();
if(user == null) {
sendError("Internal Auth error: UserSession is broken");
return;
}
client.coreObject = user; client.coreObject = user;
client.sessionObject = session; client.sessionObject = session;
server.authManager.internalAuth(client, client.type == null ? AuthResponse.ConnectTypes.API : client.type, pair, user.getUsername(), user.getUUID(), user.getPermissions(), true); server.authManager.internalAuth(client, client.type == null ? AuthResponse.ConnectTypes.API : client.type, pair, user.getUsername(), user.getUUID(), user.getPermissions(), true);

View file

@ -18,7 +18,7 @@ public String getType() {
} }
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
sendError("Legacy session system removed"); sendError("Legacy session system removed");
} }
} }

View file

@ -12,7 +12,7 @@ public String getType() {
} }
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
sendResult(new GetPublicKeyRequestEvent(server.keyAgreementManager.rsaPublicKey, server.keyAgreementManager.ecdsaPublicKey)); sendResult(new GetPublicKeyRequestEvent(server.keyAgreementManager.rsaPublicKey, server.keyAgreementManager.ecdsaPublicKey));
} }
} }

View file

@ -0,0 +1,27 @@
package pro.gravit.launchserver.socket.response.management;
import io.netty.channel.ChannelHandlerContext;
import pro.gravit.launcher.events.request.ServerStatusRequestEvent;
import pro.gravit.launchserver.socket.Client;
import pro.gravit.launchserver.socket.response.SimpleResponse;
import pro.gravit.utils.helper.JVMHelper;
public class ServerStatusResponse extends SimpleResponse {
@Override
public String getType() {
return "serverStatus";
}
@Override
public void execute(ChannelHandlerContext ctx, Client client) {
ServerStatusRequestEvent event = new ServerStatusRequestEvent(server.config.projectName);
event.totalJavaMemory = JVMHelper.RUNTIME.totalMemory();
event.freeJavaMemory = JVMHelper.RUNTIME.freeMemory();
event.shortLatency = (service.shortRequestLatency.get() / service.shortRequestCounter.get()) / 1_000_000;
event.middleLatency = (service.middleRequestLatency.get() / service.middleRequestCounter.get()) / 1_000_000;
event.longLatency = (service.longRequestLatency.get() / service.longRequestCounter.get()) / 1_000_000;
event.latency = ((service.shortRequestLatency.get() + service.middleRequestLatency.get() + service.longRequestLatency.get()) /
(service.shortRequestCounter.get() + service.middleRequestCounter.get() + service.longRequestCounter.get())) / 1_000_000;
sendResult(event);
}
}

View file

@ -16,7 +16,7 @@ public String getType() {
} }
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
BatchProfileByUsernameRequestEvent result = new BatchProfileByUsernameRequestEvent(); BatchProfileByUsernameRequestEvent result = new BatchProfileByUsernameRequestEvent();
if (list == null) { if (list == null) {
sendError("Invalid request"); sendError("Invalid request");

View file

@ -19,7 +19,7 @@ public String getType() {
} }
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
AuthProviderPair pair; AuthProviderPair pair;
if (client.auth == null) { if (client.auth == null) {
pair = server.config.getAuthProviderPair(); pair = server.config.getAuthProviderPair();

View file

@ -17,7 +17,7 @@ public String getType() {
} }
@Override @Override
public void execute(ChannelHandlerContext ctx, Client client) { public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
AuthProviderPair pair = client.auth; AuthProviderPair pair = client.auth;
if (pair == null) pair = server.config.getAuthProviderPair(); if (pair == null) pair = server.config.getAuthProviderPair();
PlayerProfile profile = server.authManager.getPlayerProfile(pair, username); PlayerProfile profile = server.authManager.getPlayerProfile(pair, username);

View file

@ -85,10 +85,12 @@ private boolean checkSecure(String hash, String salt) {
} }
public static class LauncherTokenVerifier implements RestoreResponse.ExtendedTokenProvider { public static class LauncherTokenVerifier implements RestoreResponse.ExtendedTokenProvider {
private final LaunchServer server;
private final JwtParser parser; private final JwtParser parser;
private final Logger logger = LogManager.getLogger(); private final Logger logger = LogManager.getLogger();
public LauncherTokenVerifier(LaunchServer server) { public LauncherTokenVerifier(LaunchServer server) {
this.server = server;
parser = Jwts.parserBuilder() parser = Jwts.parserBuilder()
.setSigningKey(server.keyAgreementManager.ecdsaPublicKey) .setSigningKey(server.keyAgreementManager.ecdsaPublicKey)
.requireIssuer("LaunchServer") .requireIssuer("LaunchServer")

View file

@ -0,0 +1,47 @@
{
"version": "1.10.2",
"assetIndex": "1.10.2",
"assetDir": "asset1.10",
"dir": "HiTech",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "xxxxxxxx",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar", "forge.jar", "liteloader.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.launchwrapper.Launch",
"jvmArgs": [
"-Dfml.ignorePatchDiscrepancies=true",
"-Dfml.ignoreInvalidMinecraftCertificates=true",
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
"clientArgs": [
"--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker",
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -0,0 +1,47 @@
{
"version": "1.11.2",
"assetIndex": "1.11.2",
"assetDir": "asset1.11",
"dir": "HiTech",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "xxxxxxxx",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar", "forge.jar", "liteloader.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.launchwrapper.Launch",
"jvmArgs": [
"-Dfml.ignorePatchDiscrepancies=true",
"-Dfml.ignoreInvalidMinecraftCertificates=true",
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
"clientArgs": [
"--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker",
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -0,0 +1,47 @@
{
"version": "1.12.2",
"assetIndex": "1.12.2",
"assetDir": "asset1.12",
"dir": "HiTech",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "xxxxxxxx",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar", "forge.jar", "liteloader.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.launchwrapper.Launch",
"jvmArgs": [
"-Dfml.ignorePatchDiscrepancies=true",
"-Dfml.ignoreInvalidMinecraftCertificates=true",
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
"clientArgs": [
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker",
"--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker"
],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -0,0 +1,45 @@
{
"version": "1.13.1",
"assetIndex": "1.13.1",
"assetDir": "asset1.13.1",
"dir": "HiTech",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "xxxxxxxx",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar", "forge.jar", "liteloader.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.client.main.Main",
"jvmArgs": [
"-Dfml.ignorePatchDiscrepancies=true",
"-Dfml.ignoreInvalidMinecraftCertificates=true",
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
"clientArgs": [
],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -0,0 +1,45 @@
{
"version": "1.13",
"assetIndex": "1.13",
"assetDir": "asset1.13",
"dir": "HiTech",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "xxxxxxxx",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar", "forge.jar", "liteloader.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.client.main.Main",
"jvmArgs": [
"-Dfml.ignorePatchDiscrepancies=true",
"-Dfml.ignoreInvalidMinecraftCertificates=true",
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
"clientArgs": [
],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -0,0 +1,44 @@
{
"version": "1.14.4",
"assetIndex": "1.14.4",
"assetDir": "asset1.14.4",
"dir": "HiTech",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "xxxxxxxx",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": [
"servers.dat"
],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries",
"natives",
"minecraft.jar"
],
"updateOptional": [],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.client.main.Main",
"jvmArgs": [
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": [
"minecraft.jar",
"libraries"
],
"clientArgs": [],
"whitelist": []
}

View file

@ -0,0 +1,44 @@
{
"version": "1.15.1",
"assetIndex": "1.15.1",
"assetDir": "asset1.15.1",
"dir": "HiTech",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "xxxxxxxx",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": [
"servers.dat"
],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries",
"natives",
"minecraft.jar"
],
"updateOptional": [],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.client.main.Main",
"jvmArgs": [
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": [
"minecraft.jar",
"libraries"
],
"clientArgs": [],
"whitelist": []
}

View file

@ -0,0 +1,44 @@
{
"version": "1.15.2",
"assetIndex": "1.15.2",
"assetDir": "asset1.15.2",
"dir": "HiTech",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "xxxxxxxx",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": [
"servers.dat"
],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries",
"natives",
"minecraft.jar"
],
"updateOptional": [],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.client.main.Main",
"jvmArgs": [
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": [
"minecraft.jar",
"libraries"
],
"clientArgs": [],
"whitelist": []
}

View file

@ -0,0 +1,44 @@
{
"version": "1.16.1",
"assetIndex": "1.16.1",
"assetDir": "asset1.16.1",
"dir": "HiTech",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "xxxxxxxx",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": [
"servers.dat"
],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries",
"natives",
"minecraft.jar"
],
"updateOptional": [],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.client.main.Main",
"jvmArgs": [
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": [
"minecraft.jar",
"libraries"
],
"clientArgs": [],
"whitelist": []
}

View file

@ -0,0 +1,44 @@
{
"version": "1.4.7",
"assetIndex": "---",
"assetDir": "asset1.4.7",
"dir": "xxxxxxx",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "Test1.4.7",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.launchwrapper.Launch",
"jvmArgs": [
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism",
"-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png",
"-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png"
],
"classPath": ["minecraft.jar", "libraries"],
"clientArgs": [],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -0,0 +1,44 @@
{
"version": "1.5.2",
"assetIndex": "---",
"assetDir": "asset1.5.2",
"dir": "xxxxxxx",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "Test1.5.2",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.launchwrapper.Launch",
"jvmArgs": [
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism",
"-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png",
"-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png"
],
"classPath": ["minecraft.jar", "libraries"],
"clientArgs": [],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -0,0 +1,49 @@
{
"version": "1.6.4",
"assetIndex": "---",
"assetDir": "asset1.6.4",
"dir": "xxxxxxx",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "Test1.6.4",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar", "forge.jar", "liteloader.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.launchwrapper.Launch",
"jvmArgs": [
"-Dfml.ignorePatchDiscrepancies=true",
"-Dfml.ignoreInvalidMinecraftCertificates=true",
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism",
"-Dlauncher.legacy.skinsURL=http://skins.minecraft.net/MinecraftSkins/%username%.png",
"-Dlauncher.legacy.cloaksURL=http://skins.minecraft.net/MinecraftCloaks/%username%.png"
],
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
"clientArgs": [
"--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker",
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -0,0 +1,47 @@
{
"version": "1.7.10",
"assetIndex": "1.7.10",
"assetDir": "asset1.7.10",
"dir": "xxxxxxx",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "Test1.7.10",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar", "forge.jar", "liteloader.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.launchwrapper.Launch",
"jvmArgs": [
"-Dfml.ignorePatchDiscrepancies=true",
"-Dfml.ignoreInvalidMinecraftCertificates=true",
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
"clientArgs": [
"--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker",
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -0,0 +1,47 @@
{
"version": "1.7.2",
"assetIndex": "1.7.2",
"assetDir": "asset1.7.2",
"dir": "xxxxxxx",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "Test1.7.2",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar", "forge.jar", "liteloader.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.launchwrapper.Launch",
"jvmArgs": [
"-Dfml.ignorePatchDiscrepancies=true",
"-Dfml.ignoreInvalidMinecraftCertificates=true",
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
"clientArgs": [
"--tweakClass", "cpw.mods.fml.common.launcher.FMLTweaker",
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -0,0 +1,47 @@
{
"version": "1.8.9",
"assetIndex": "1.8.9",
"assetDir": "asset1.8.9",
"dir": "xxxxxxx",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "Test1.8.9",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar", "forge.jar", "liteloader.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.launchwrapper.Launch",
"jvmArgs": [
"-Dfml.ignorePatchDiscrepancies=true",
"-Dfml.ignoreInvalidMinecraftCertificates=true",
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
"clientArgs": [
"--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker",
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -0,0 +1,47 @@
{
"version": "1.9.4",
"assetIndex": "1.9.4",
"assetDir": "asset1.9.4",
"dir": "xxxxxxx",
"info": "Информация о сервере",
"sortIndex": 0,
"title": "Test1.9.4",
"servers": [
{
"name": "----",
"serverAddress": "localhost",
"serverPort": 25565,
"isDefault": true
}
],
"update": ["servers.dat"],
"updateExclusions": [],
"updateShared": [],
"updateVerify": [
"libraries", "natives", "mods",
"minecraft.jar", "forge.jar", "liteloader.jar"
],
"updateOptional": [
],
"updateFastCheck": true,
"useWhitelist": false,
"mainClass": "net.minecraft.launchwrapper.Launch",
"jvmArgs": [
"-Dfml.ignorePatchDiscrepancies=true",
"-Dfml.ignoreInvalidMinecraftCertificates=true",
"-XX:+UseConcMarkSweepGC",
"-XX:+CMSIncrementalMode",
"-XX:-UseAdaptiveSizePolicy",
"-Xmn128M",
"-XX:+DisableAttachMechanism"
],
"classPath": ["forge.jar", "liteloader.jar", "minecraft.jar", "libraries"],
"clientArgs": [
"--tweakClass", "net.minecraftforge.fml.common.launcher.FMLTweaker",
"--tweakClass", "com.mumfrey.liteloader.launch.LiteLoaderTweaker"
],
"optionalJVMArgs": [],
"optionalClientArgs": [],
"optionalClassPath": [],
"whitelist": []
}

View file

@ -21,7 +21,7 @@ public class ASMTransformersTest {
public static ASMClassLoader classLoader; public static ASMClassLoader classLoader;
@BeforeAll @BeforeAll
public static void prepare() { public static void prepare() throws Throwable {
classLoader = new ASMClassLoader(ASMTransformersTest.class.getClassLoader()); classLoader = new ASMClassLoader(ASMTransformersTest.class.getClassLoader());
} }

View file

@ -2,7 +2,6 @@
import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir; import org.junit.jupiter.api.io.TempDir;
import pro.gravit.launcher.Launcher; import pro.gravit.launcher.Launcher;
import pro.gravit.launchserver.config.LaunchServerConfig; import pro.gravit.launchserver.config.LaunchServerConfig;
@ -46,9 +45,4 @@ public static void prepare() throws Throwable {
.setCommandHandler(new StdCommandHandler(false)); .setCommandHandler(new StdCommandHandler(false));
launchServer = builder.build(); launchServer = builder.build();
} }
@Test
public void test() {
}
} }

View file

@ -4,6 +4,8 @@
import pro.gravit.launchserver.config.LaunchServerConfig; import pro.gravit.launchserver.config.LaunchServerConfig;
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig; import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
import java.io.IOException;
public class TestLaunchServerConfigManager implements LaunchServer.LaunchServerConfigManager { public class TestLaunchServerConfigManager implements LaunchServer.LaunchServerConfigManager {
public LaunchServerConfig config; public LaunchServerConfig config;
public LaunchServerRuntimeConfig runtimeConfig; public LaunchServerRuntimeConfig runtimeConfig;
@ -15,22 +17,22 @@ public TestLaunchServerConfigManager() {
} }
@Override @Override
public LaunchServerConfig readConfig() { public LaunchServerConfig readConfig() throws IOException {
return config; return config;
} }
@Override @Override
public LaunchServerRuntimeConfig readRuntimeConfig() { public LaunchServerRuntimeConfig readRuntimeConfig() throws IOException {
return runtimeConfig; return runtimeConfig;
} }
@Override @Override
public void writeConfig(LaunchServerConfig config) { public void writeConfig(LaunchServerConfig config) throws IOException {
} }
@Override @Override
public void writeRuntimeConfig(LaunchServerRuntimeConfig config) { public void writeRuntimeConfig(LaunchServerRuntimeConfig config) throws IOException {
} }
} }

View file

@ -29,12 +29,12 @@
"Multi-Release": "true") "Multi-Release": "true")
} }
tasks.register('sourcesJar', Jar) { task sourcesJar(type: Jar) {
from sourceSets.main.allJava from sourceSets.main.allJava
archiveClassifier.set('sources') archiveClassifier.set('sources')
} }
tasks.register('javadocJar', Jar) { task javadocJar(type: Jar) {
from javadoc from javadoc
archiveClassifier.set('javadoc') archiveClassifier.set('javadoc')
} }
@ -53,14 +53,14 @@ pack project(':LauncherAPI')
pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty'] pack group: 'io.netty', name: 'netty-codec-http', version: rootProject['verNetty']
} }
tasks.register('genRuntimeJS', Zip) { task genRuntimeJS(type: Zip) {
duplicatesStrategy = 'EXCLUDE' duplicatesStrategy = 'EXCLUDE'
archiveFileName = "runtime.zip" archiveFileName = "runtime.zip"
destinationDirectory = file("${buildDir}/tmp") destinationDirectory = file("${buildDir}/tmp")
from "runtime/" from "runtime/"
} }
tasks.register('dumpLibs', Copy) { task dumpLibs(type: Copy) {
duplicatesStrategy = 'EXCLUDE' duplicatesStrategy = 'EXCLUDE'
into "$buildDir/libs/libraries" into "$buildDir/libs/libraries"
from configurations.bundle from configurations.bundle

View file

@ -83,6 +83,8 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
} }
context.executePath = IOHelper.resolveJavaBin(context.javaVersion.jvmDir); context.executePath = IOHelper.resolveJavaBin(context.javaVersion.jvmDir);
//List<String> args = new LinkedList<>();
//args.add(javaBin.toString());
String pathLauncher = IOHelper.getCodeSource(LauncherEngine.class).toString(); String pathLauncher = IOHelper.getCodeSource(LauncherEngine.class).toString();
context.mainClass = LauncherEngine.class.getName(); context.mainClass = LauncherEngine.class.getName();
context.memoryLimit = launcherMemoryLimit; context.memoryLimit = launcherMemoryLimit;
@ -141,12 +143,8 @@ public static void main(String[] arguments) throws IOException, InterruptedExcep
if (customJvmOptions != null) { if (customJvmOptions != null) {
args.addAll(customJvmOptions); args.addAll(customJvmOptions);
} }
if(context.useLegacyClasspathProperty) {
args.add(String.format("-Djava.class.path=%s", String.join(IOHelper.PLATFORM_SEPARATOR, context.classpath)));
} else {
args.add("-cp"); args.add("-cp");
args.add(String.join(IOHelper.PLATFORM_SEPARATOR, context.classpath)); args.add(String.join(IOHelper.PLATFORM_SEPARATOR, context.classpath));
}
args.add(context.mainClass); args.add(context.mainClass);
args.addAll(context.clientArgs); args.addAll(context.clientArgs);
LogHelper.debug("Commandline: " + args); LogHelper.debug("Commandline: " + args);
@ -174,7 +172,6 @@ public static class ClientLauncherWrapperContext {
public Path executePath; public Path executePath;
public String mainClass; public String mainClass;
public int memoryLimit; public int memoryLimit;
public boolean useLegacyClasspathProperty;
public ProcessBuilder processBuilder; public ProcessBuilder processBuilder;
public List<String> args = new ArrayList<>(8); public List<String> args = new ArrayList<>(8);
public Map<String, String> jvmProperties = new HashMap<>(); public Map<String, String> jvmProperties = new HashMap<>();

View file

@ -8,6 +8,9 @@
import pro.gravit.launcher.console.ModulesCommand; import pro.gravit.launcher.console.ModulesCommand;
import pro.gravit.launcher.console.SignDataCommand; import pro.gravit.launcher.console.SignDataCommand;
import pro.gravit.launcher.events.request.*; import pro.gravit.launcher.events.request.*;
import pro.gravit.launcher.guard.LauncherGuard;
import pro.gravit.launcher.guard.LauncherNoGuard;
import pro.gravit.launcher.guard.LauncherWrapperGuard;
import pro.gravit.launcher.gui.NoRuntimeProvider; import pro.gravit.launcher.gui.NoRuntimeProvider;
import pro.gravit.launcher.gui.RuntimeProvider; import pro.gravit.launcher.gui.RuntimeProvider;
import pro.gravit.launcher.managers.ClientGsonManager; import pro.gravit.launcher.managers.ClientGsonManager;
@ -46,6 +49,7 @@
public class LauncherEngine { public class LauncherEngine {
public static ClientLauncherProcess.ClientParams clientParams; public static ClientLauncherProcess.ClientParams clientParams;
public static LauncherGuard guard;
public static ClientModuleManager modulesManager; public static ClientModuleManager modulesManager;
public final boolean clientInstance; public final boolean clientInstance;
// Instance // Instance
@ -130,6 +134,8 @@ public static void main(String... args) throws Throwable {
} }
long endTime = System.currentTimeMillis(); long endTime = System.currentTimeMillis();
LogHelper.debug("Launcher started in %dms", endTime - startTime); LogHelper.debug("Launcher started in %dms", endTime - startTime);
//Request.service.close();
//FunctionalBridge.close();
LauncherEngine.exitLauncher(0); LauncherEngine.exitLauncher(0);
} }
@ -147,6 +153,16 @@ public static void verifyNoAgent() {
throw new SecurityException("JavaAgent found"); throw new SecurityException("JavaAgent found");
} }
public static LauncherGuard tryGetStdGuard() {
switch (Launcher.getConfig().guardType) {
case "no":
return new LauncherNoGuard();
case "wrapper":
return new LauncherWrapperGuard();
}
return null;
}
public static RequestService initOffline() { public static RequestService initOffline() {
OfflineRequestService service = new OfflineRequestService(); OfflineRequestService service = new OfflineRequestService();
applyBasicOfflineProcessors(service); applyBasicOfflineProcessors(service);
@ -216,6 +232,7 @@ public void readKeys() throws IOException, InvalidKeySpecException {
public void start(String... args) throws Throwable { public void start(String... args) throws Throwable {
//Launcher.modulesManager = new ClientModuleManager(this); //Launcher.modulesManager = new ClientModuleManager(this);
LauncherEngine.guard = tryGetStdGuard();
ClientPreGuiPhase event = new ClientPreGuiPhase(null); ClientPreGuiPhase event = new ClientPreGuiPhase(null);
LauncherEngine.modulesManager.invokeEvent(event); LauncherEngine.modulesManager.invokeEvent(event);
runtimeProvider = event.runtimeProvider; runtimeProvider = event.runtimeProvider;

View file

@ -5,15 +5,10 @@
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
public class ClientClassLoader extends URLClassLoader { public class ClientClassLoader extends URLClassLoader {
private static final ClassLoader SYSTEM_CLASS_LOADER = ClassLoader.getSystemClassLoader();
public String nativePath; public String nativePath;
private final List<String> packages = new ArrayList<>();
/** /**
* Constructs a new URLClassLoader for the specified URLs using the * Constructs a new URLClassLoader for the specified URLs using the
* default delegation parent {@code ClassLoader}. The URLs will * default delegation parent {@code ClassLoader}. The URLs will
@ -32,11 +27,10 @@ public class ClientClassLoader extends URLClassLoader {
* {@code checkCreateClassLoader} method doesn't allow * {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader. * creation of a class loader.
* @throws NullPointerException if {@code urls} is {@code null}. * @throws NullPointerException if {@code urls} is {@code null}.
* @see SecurityManager#checkCreateClassLoader
*/ */
public ClientClassLoader(URL[] urls) { public ClientClassLoader(URL[] urls) {
super(urls); super(urls);
packages.add("pro.gravit.launcher.");
packages.add("pro.gravit.utils.");
} }
/** /**
@ -58,23 +52,12 @@ public ClientClassLoader(URL[] urls) {
* {@code checkCreateClassLoader} method doesn't allow * {@code checkCreateClassLoader} method doesn't allow
* creation of a class loader. * creation of a class loader.
* @throws NullPointerException if {@code urls} is {@code null}. * @throws NullPointerException if {@code urls} is {@code null}.
* @see SecurityManager#checkCreateClassLoader
*/ */
public ClientClassLoader(URL[] urls, ClassLoader parent) { public ClientClassLoader(URL[] urls, ClassLoader parent) {
super(urls, parent); super(urls, parent);
} }
@Override
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
if(name != null) {
for(String pkg : packages) {
if(name.startsWith(pkg)) {
return SYSTEM_CLASS_LOADER.loadClass(name);
}
}
}
return super.loadClass(name, resolve);
}
@Override @Override
public String findLibrary(String name) { public String findLibrary(String name) {
return nativePath.concat(IOHelper.PLATFORM_SEPARATOR).concat(getNativePrefix()).concat(name).concat(getNativeEx()); return nativePath.concat(IOHelper.PLATFORM_SEPARATOR).concat(getNativePrefix()).concat(name).concat(getNativeEx());
@ -98,10 +81,6 @@ else if (JVMHelper.OS_TYPE == JVMHelper.OS.MACOSX)
return ""; return "";
} }
public void addAllowedPackage(String pkg) {
packages.add(pkg);
}
@Override @Override
public void addURL(URL url) { public void addURL(URL url) {
super.addURL(url); super.addURL(url);

View file

@ -16,7 +16,6 @@
import pro.gravit.launcher.modules.events.OfflineModeEvent; import pro.gravit.launcher.modules.events.OfflineModeEvent;
import pro.gravit.launcher.modules.events.PreConfigPhase; import pro.gravit.launcher.modules.events.PreConfigPhase;
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launcher.profiles.ClientProfileVersions;
import pro.gravit.launcher.profiles.optional.actions.OptionalAction; import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClassPath; import pro.gravit.launcher.profiles.optional.actions.OptionalActionClassPath;
import pro.gravit.launcher.profiles.optional.actions.OptionalActionClientArgs; import pro.gravit.launcher.profiles.optional.actions.OptionalActionClientArgs;
@ -34,6 +33,7 @@
import pro.gravit.launcher.utils.DirWatcher; import pro.gravit.launcher.utils.DirWatcher;
import pro.gravit.utils.helper.*; import pro.gravit.utils.helper.*;
import javax.swing.*;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandle;
@ -46,7 +46,6 @@
import java.nio.file.SimpleFileVisitor; import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes; import java.nio.file.attribute.BasicFileAttributes;
import java.util.*; import java.util.*;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -108,6 +107,7 @@ public static void main(String[] args) throws Throwable {
} else if (params.session != null) { } else if (params.session != null) {
throw new UnsupportedOperationException("Legacy session not supported"); throw new UnsupportedOperationException("Legacy session not supported");
} }
checkJVMBitsAndVersion(params.profile.getMinJavaVersion(), params.profile.getRecommendJavaVersion(), params.profile.getMaxJavaVersion(), params.profile.isWarnMissJavaVersion());
LauncherEngine.modulesManager.invokeEvent(new ClientProcessInitPhase(engine, params)); LauncherEngine.modulesManager.invokeEvent(new ClientProcessInitPhase(engine, params));
Path clientDir = Paths.get(params.clientDir); Path clientDir = Paths.get(params.clientDir);
@ -144,7 +144,7 @@ public static void main(String[] args) throws Throwable {
LogHelper.debug("Natives dir %s", params.nativesDir); LogHelper.debug("Natives dir %s", params.nativesDir);
ClientProfile.ClassLoaderConfig classLoaderConfig = profile.getClassLoaderConfig(); ClientProfile.ClassLoaderConfig classLoaderConfig = profile.getClassLoaderConfig();
if (classLoaderConfig == ClientProfile.ClassLoaderConfig.LAUNCHER) { if (classLoaderConfig == ClientProfile.ClassLoaderConfig.LAUNCHER) {
ClientClassLoader classLoader = new ClientClassLoader(classpathURLs.toArray(new URL[0]), ClientLauncherEntryPoint.class.getClassLoader()); ClientClassLoader classLoader = new ClientClassLoader(classpathURLs.toArray(new URL[0]), ClassLoader.getSystemClassLoader());
System.setProperty("java.class.path", classpath.stream().map(Path::toString).collect(Collectors.joining(File.pathSeparator))); System.setProperty("java.class.path", classpath.stream().map(Path::toString).collect(Collectors.joining(File.pathSeparator)));
ClientLauncherEntryPoint.classLoader = classLoader; ClientLauncherEntryPoint.classLoader = classLoader;
Thread.currentThread().setContextClassLoader(classLoader); Thread.currentThread().setContextClassLoader(classLoader);
@ -174,6 +174,15 @@ public static void main(String[] args) throws Throwable {
AuthService.username = params.playerProfile.username; AuthService.username = params.playerProfile.username;
AuthService.uuid = params.playerProfile.uuid; AuthService.uuid = params.playerProfile.uuid;
KeyService.serverRsaPublicKey = Launcher.getConfig().rsaPublicKey; KeyService.serverRsaPublicKey = Launcher.getConfig().rsaPublicKey;
if (params.profile.getRuntimeInClientConfig() != ClientProfile.RuntimeInClientConfig.NONE) {
CommonHelper.newThread("Client Launcher Thread", true, () -> {
try {
engine.start(args);
} catch (Throwable throwable) {
LogHelper.error(throwable);
}
}).start();
}
LauncherEngine.modulesManager.invokeEvent(new ClientProcessReadyEvent(engine, params)); LauncherEngine.modulesManager.invokeEvent(new ClientProcessReadyEvent(engine, params));
LogHelper.debug("Starting JVM and client WatchService"); LogHelper.debug("Starting JVM and client WatchService");
FileNameMatcher assetMatcher = profile.getAssetUpdateMatcher(); FileNameMatcher assetMatcher = profile.getAssetUpdateMatcher();
@ -242,26 +251,45 @@ public static void verifyHDir(Path dir, HashedDir hdir, FileNameMatcher matcher,
// Hash directory and compare (ignore update-only matcher entries, it will break offline-mode) // Hash directory and compare (ignore update-only matcher entries, it will break offline-mode)
HashedDir currentHDir = new HashedDir(dir, matcher, true, digest); HashedDir currentHDir = new HashedDir(dir, matcher, true, digest);
HashedDir.Diff diff = hdir.diff(currentHDir, matcher); HashedDir.Diff diff = hdir.diff(currentHDir, matcher);
AtomicReference<String> latestPath = new AtomicReference<>("unknown");
if (!diff.mismatch.isEmpty() || (checkExtra && !diff.extra.isEmpty())) { if (!diff.mismatch.isEmpty() || (checkExtra && !diff.extra.isEmpty())) {
diff.extra.walk(File.separator, (e, k, v) -> { diff.extra.walk(File.separator, (e, k, v) -> {
if (v.getType().equals(HashedEntry.Type.FILE)) { if (v.getType().equals(HashedEntry.Type.FILE)) {
LogHelper.error("Extra file %s", e); LogHelper.error("Extra file %s", e);
latestPath.set(e);
} else LogHelper.error("Extra %s", e); } else LogHelper.error("Extra %s", e);
return HashedDir.WalkAction.CONTINUE; return HashedDir.WalkAction.CONTINUE;
}); });
diff.mismatch.walk(File.separator, (e, k, v) -> { diff.mismatch.walk(File.separator, (e, k, v) -> {
if (v.getType().equals(HashedEntry.Type.FILE)) { if (v.getType().equals(HashedEntry.Type.FILE)) {
LogHelper.error("Mismatch file %s", e); LogHelper.error("Mismatch file %s", e);
latestPath.set(e);
} else LogHelper.error("Mismatch %s", e); } else LogHelper.error("Mismatch %s", e);
return HashedDir.WalkAction.CONTINUE; return HashedDir.WalkAction.CONTINUE;
}); });
throw new SecurityException(String.format("Forbidden modification: '%s' file '%s'", IOHelper.getFileName(dir), latestPath.get())); throw new SecurityException(String.format("Forbidden modification: '%s'", IOHelper.getFileName(dir)));
} }
} }
public static boolean checkJVMBitsAndVersion(int minVersion, int recommendVersion, int maxVersion, boolean showMessage) {
boolean ok = true;
if (JVMHelper.JVM_BITS == 64 && JVMHelper.ARCH_TYPE == JVMHelper.ARCH.X86) {
String error = "У Вас установлена Java x64, но Ваша система определена как x32. Установите Java правильной разрядности";
LogHelper.error(error);
if (showMessage)
JOptionPane.showMessageDialog(null, error);
ok = false;
}
String jvmVersion = JVMHelper.RUNTIME_MXBEAN.getVmVersion();
LogHelper.info(jvmVersion);
int version = JVMHelper.getVersion();
if (version < minVersion || version > maxVersion) {
String error = String.format("У Вас установлена Java %d, но этот клиент требует Java %d", JVMHelper.getVersion(), recommendVersion);
LogHelper.error(error);
if (showMessage)
JOptionPane.showMessageDialog(null, error);
ok = false;
}
return ok;
}
private static LinkedList<Path> resolveClassPathList(Path clientDir, String... classPath) throws IOException { private static LinkedList<Path> resolveClassPathList(Path clientDir, String... classPath) throws IOException {
return resolveClassPathStream(clientDir, classPath).collect(Collectors.toCollection(LinkedList::new)); return resolveClassPathStream(clientDir, classPath).collect(Collectors.toCollection(LinkedList::new));
} }
@ -291,7 +319,7 @@ public static Stream<Path> resolveClassPath(Path clientDir, Set<OptionalAction>
private static void launch(ClientProfile profile, ClientLauncherProcess.ClientParams params) throws Throwable { private static void launch(ClientProfile profile, ClientLauncherProcess.ClientParams params) throws Throwable {
// Add client args // Add client args
Collection<String> args = new LinkedList<>(); Collection<String> args = new LinkedList<>();
if (profile.getVersion().compareTo(ClientProfileVersions.MINECRAFT_1_6_4) >= 0) if (profile.getVersion().compareTo(ClientProfile.Version.MC164) >= 0)
params.addClientArgs(args); params.addClientArgs(args);
else { else {
params.addClientLegacyArgs(args); params.addClientLegacyArgs(args);
@ -325,7 +353,7 @@ private static void launch(ClientProfile profile, ClientLauncherProcess.ClientPa
List<String> compatClasses = profile.getCompatClasses(); List<String> compatClasses = profile.getCompatClasses();
for (String e : compatClasses) { for (String e : compatClasses) {
Class<?> clazz = classLoader.loadClass(e); Class<?> clazz = classLoader.loadClass(e);
MethodHandle runMethod = MethodHandles.lookup().findStatic(clazz, "run", MethodType.methodType(void.class)); MethodHandle runMethod = MethodHandles.publicLookup().findStatic(clazz, "run", MethodType.methodType(void.class));
runMethod.invoke(); runMethod.invoke();
} }
} }

View file

@ -10,7 +10,6 @@
import pro.gravit.launcher.events.request.AuthRequestEvent; import pro.gravit.launcher.events.request.AuthRequestEvent;
import pro.gravit.launcher.hasher.HashedDir; import pro.gravit.launcher.hasher.HashedDir;
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launcher.profiles.ClientProfileVersions;
import pro.gravit.launcher.profiles.PlayerProfile; import pro.gravit.launcher.profiles.PlayerProfile;
import pro.gravit.launcher.profiles.optional.OptionalView; import pro.gravit.launcher.profiles.optional.OptionalView;
import pro.gravit.launcher.profiles.optional.actions.OptionalAction; import pro.gravit.launcher.profiles.optional.actions.OptionalAction;
@ -32,8 +31,6 @@
import java.util.stream.Collectors; import java.util.stream.Collectors;
public class ClientLauncherProcess { public class ClientLauncherProcess {
public final List<String> pre = new LinkedList<>();
public final ClientParams params = new ClientParams(); public final ClientParams params = new ClientParams();
public final List<String> jvmArgs = new LinkedList<>(); public final List<String> jvmArgs = new LinkedList<>();
public final List<String> jvmModules = new LinkedList<>(); public final List<String> jvmModules = new LinkedList<>();
@ -79,14 +76,9 @@ public ClientLauncherProcess(Path clientDir, Path assetDir, JavaHelper.JavaVersi
this.params.clientDir = this.workDir.toString(); this.params.clientDir = this.workDir.toString();
this.params.resourcePackDir = resourcePackDir.toAbsolutePath().toString(); this.params.resourcePackDir = resourcePackDir.toAbsolutePath().toString();
this.params.assetDir = assetDir.toAbsolutePath().toString(); this.params.assetDir = assetDir.toAbsolutePath().toString();
Path nativesPath; Path nativesPath = workDir.resolve("natives").resolve(JVMHelper.OS_TYPE.name).resolve(javaVersion.arch.name);
if(profile.hasFlag(ClientProfile.CompatibilityFlags.LEGACY_NATIVES_DIR)) {
nativesPath = workDir.resolve("natives");
} else {
nativesPath = workDir.resolve("natives").resolve(JVMHelper.OS_TYPE.name).resolve(javaVersion.arch.name);
}
if (!Files.isDirectory(nativesPath)) { if (!Files.isDirectory(nativesPath)) {
throw new RuntimeException(String.format("Natives dir %s not exist! Your operating system or architecture not supported", nativesPath.toAbsolutePath())); nativesPath = workDir.resolve("natives");
} }
this.params.nativesDir = nativesPath.toString(); this.params.nativesDir = nativesPath.toString();
this.params.profile = profile; this.params.profile = profile;
@ -131,13 +123,24 @@ private void applyClientProfile() {
} }
this.jvmModules.addAll(this.params.profile.getModules()); this.jvmModules.addAll(this.params.profile.getModules());
this.jvmModulesPaths.addAll(this.params.profile.getModulePath()); this.jvmModulesPaths.addAll(this.params.profile.getModulePath());
if (this.params.profile.getRuntimeInClientConfig() != ClientProfile.RuntimeInClientConfig.NONE) {
jvmModules.add("javafx.base");
jvmModules.add("javafx.graphics");
jvmModules.add("javafx.fxml");
jvmModules.add("javafx.controls");
jvmModules.add("javafx.swing");
jvmModules.add("javafx.media");
jvmModules.add("javafx.web");
}
LauncherEngine.modulesManager.invokeEvent(new ClientProcessBuilderCreateEvent(this)); LauncherEngine.modulesManager.invokeEvent(new ClientProcessBuilderCreateEvent(this));
} }
public void start(boolean pipeOutput) throws IOException, InterruptedException { public void start(boolean pipeOutput) throws IOException, InterruptedException {
if (isStarted) throw new IllegalStateException("Process already started"); if (isStarted) throw new IllegalStateException("Process already started");
if (LauncherEngine.guard != null) LauncherEngine.guard.applyGuardParams(this);
LauncherEngine.modulesManager.invokeEvent(new ClientProcessBuilderPreLaunchEvent(this)); LauncherEngine.modulesManager.invokeEvent(new ClientProcessBuilderPreLaunchEvent(this));
List<String> processArgs = new LinkedList<>(pre); List<String> processArgs = new LinkedList<>();
processArgs.add(executeFile.toString()); processArgs.add(executeFile.toString());
processArgs.addAll(jvmArgs); processArgs.addAll(jvmArgs);
if (javaVersion.version >= 9) { if (javaVersion.version >= 9) {
@ -189,10 +192,20 @@ public void start(boolean pipeOutput) throws IOException, InterruptedException {
} }
private void applyJava9Params(List<String> processArgs) { private void applyJava9Params(List<String> processArgs) {
// TODO: fix runtime in client /*jvmModulesPaths.add(javaVersion.jvmDir);
jvmModulesPaths.add(javaVersion.jvmDir.resolve("jre"));
Path openjfxPath = JavaHelper.tryGetOpenJFXPath(javaVersion.jvmDir);
if (openjfxPath != null) {
jvmModulesPaths.add(openjfxPath);
}*/ // TODO: fix runtime in client
StringBuilder modulesPath = new StringBuilder(); StringBuilder modulesPath = new StringBuilder();
StringBuilder modulesAdd = new StringBuilder(); StringBuilder modulesAdd = new StringBuilder();
for (String moduleName : jvmModules) { for (String moduleName : jvmModules) {
/*boolean success = JavaHelper.tryAddModule(jvmModulesPaths, moduleName, modulesPath);
if (success) {
if (modulesAdd.length() > 0) modulesAdd.append(",");
modulesAdd.append(moduleName);
}*/
if (modulesAdd.length() > 0) modulesAdd.append(","); if (modulesAdd.length() > 0) modulesAdd.append(",");
modulesAdd.append(moduleName); modulesAdd.append(moduleName);
} }
@ -290,7 +303,7 @@ public static class ClientParams {
public transient HashedDir javaHDir; public transient HashedDir javaHDir;
public void addClientArgs(Collection<String> args) { public void addClientArgs(Collection<String> args) {
if (profile.getVersion().compareTo(ClientProfileVersions.MINECRAFT_1_6_4) >= 0) if (profile.getVersion().compareTo(ClientProfile.Version.MC164) >= 0)
addModernClientArgs(args); addModernClientArgs(args);
else else
addClientLegacyArgs(args); addClientLegacyArgs(args);
@ -301,7 +314,7 @@ public void addClientLegacyArgs(Collection<String> args) {
args.add(accessToken); args.add(accessToken);
// Add args for tweaker // Add args for tweaker
Collections.addAll(args, "--version", profile.getVersion().toString()); Collections.addAll(args, "--version", profile.getVersion().name);
Collections.addAll(args, "--gameDir", clientDir); Collections.addAll(args, "--gameDir", clientDir);
Collections.addAll(args, "--assetsDir", assetDir); Collections.addAll(args, "--assetsDir", assetDir);
} }
@ -311,12 +324,12 @@ private void addModernClientArgs(Collection<String> args) {
// Add version-dependent args // Add version-dependent args
ClientProfile.Version version = profile.getVersion(); ClientProfile.Version version = profile.getVersion();
Collections.addAll(args, "--username", playerProfile.username); Collections.addAll(args, "--username", playerProfile.username);
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_2) >= 0) { if (version.compareTo(ClientProfile.Version.MC172) >= 0) {
Collections.addAll(args, "--uuid", Launcher.toHash(playerProfile.uuid)); Collections.addAll(args, "--uuid", Launcher.toHash(playerProfile.uuid));
Collections.addAll(args, "--accessToken", accessToken); Collections.addAll(args, "--accessToken", accessToken);
// Add 1.7.10+ args (user properties, asset index) // Add 1.7.10+ args (user properties, asset index)
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_7_10) >= 0) { if (version.compareTo(ClientProfile.Version.MC1710) >= 0) {
// Add user properties // Add user properties
Collections.addAll(args, "--userType", "mojang"); Collections.addAll(args, "--userType", "mojang");
Collections.addAll(args, "--userProperties", "{}"); Collections.addAll(args, "--userProperties", "{}");
@ -328,11 +341,11 @@ private void addModernClientArgs(Collection<String> args) {
Collections.addAll(args, "--session", accessToken); Collections.addAll(args, "--session", accessToken);
// Add version and dirs args // Add version and dirs args
Collections.addAll(args, "--version", profile.getVersion().toString()); Collections.addAll(args, "--version", profile.getVersion().name);
Collections.addAll(args, "--gameDir", clientDir); Collections.addAll(args, "--gameDir", clientDir);
Collections.addAll(args, "--assetsDir", assetDir); Collections.addAll(args, "--assetsDir", assetDir);
Collections.addAll(args, "--resourcePackDir", resourcePackDir); Collections.addAll(args, "--resourcePackDir", resourcePackDir);
if (version.compareTo(ClientProfileVersions.MINECRAFT_1_9_4) >= 0) if (version.compareTo(ClientProfile.Version.MC194) >= 0)
Collections.addAll(args, "--versionType", "Launcher v" + Version.getVersion().getVersionString()); Collections.addAll(args, "--versionType", "Launcher v" + Version.getVersion().getVersionString());
// Add server args // Add server args

View file

@ -112,17 +112,6 @@ public static Path getGuardDir() {
return dir.resolve("guard"); return dir.resolve("guard");
} }
public static Path getGuardDir(JVMHelper.ARCH arch, JVMHelper.OS os) {
Path dir = getGuardDir().resolve(Launcher.makeSpecialGuardDirName(arch, os));
try {
IOHelper.createParentDirs(dir);
} catch (Throwable e) {
throw new RuntimeException(e);
}
return dir;
}
public static Path getLegacyLauncherDir(String projectname) { public static Path getLegacyLauncherDir(String projectname) {
return IOHelper.HOME_DIR.resolve(projectname); return IOHelper.HOME_DIR.resolve(projectname);
} }

View file

@ -4,7 +4,6 @@
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.google.gson.JsonParser; import com.google.gson.JsonParser;
import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.ClientProfile;
import pro.gravit.launcher.profiles.ClientProfileVersions;
import pro.gravit.launcher.serialize.HInput; import pro.gravit.launcher.serialize.HInput;
import pro.gravit.launcher.serialize.HOutput; import pro.gravit.launcher.serialize.HOutput;
import pro.gravit.utils.helper.IOHelper; import pro.gravit.utils.helper.IOHelper;
@ -30,7 +29,6 @@ public final class ServerPinger {
private static final int PACKET_LENGTH = 65535; private static final int PACKET_LENGTH = 65535;
// Instance // Instance
private final InetSocketAddress address; private final InetSocketAddress address;
private final int protocol;
private final ClientProfile.Version version; private final ClientProfile.Version version;
// Cache // Cache
private final Object cacheLock = new Object(); private final Object cacheLock = new Object();
@ -48,7 +46,6 @@ public ServerPinger(ClientProfile.ServerProfile profile, ClientProfile.Version v
} }
this.address = profile.toSocketAddress(); this.address = profile.toSocketAddress();
this.version = Objects.requireNonNull(version, "version"); this.version = Objects.requireNonNull(version, "version");
this.protocol = profile.protocol;
} }
private static String readUTF16String(HInput input) throws IOException { private static String readUTF16String(HInput input) throws IOException {
@ -67,7 +64,7 @@ private Result doPing() throws IOException {
socket.connect(IOHelper.resolve(address), IOHelper.SOCKET_TIMEOUT); socket.connect(IOHelper.resolve(address), IOHelper.SOCKET_TIMEOUT);
try (HInput input = new HInput(socket.getInputStream()); try (HInput input = new HInput(socket.getInputStream());
HOutput output = new HOutput(socket.getOutputStream())) { HOutput output = new HOutput(socket.getOutputStream())) {
return version.compareTo(ClientProfileVersions.MINECRAFT_1_7_2) >= 0 ? modernPing(input, output, protocol) : legacyPing(input, output, version.compareTo(ClientProfileVersions.MINECRAFT_1_6_4) >= 0); return version.compareTo(ClientProfile.Version.MC172) >= 0 ? modernPing(input, output) : legacyPing(input, output, version.compareTo(ClientProfile.Version.MC164) >= 0);
} }
} }
} }
@ -83,7 +80,7 @@ private Result legacyPing(HInput input, HOutput output, boolean mc16) throws IOE
byte[] customPayloadPacket; byte[] customPayloadPacket;
try (ByteArrayOutputStream packetArray = IOHelper.newByteArrayOutput()) { try (ByteArrayOutputStream packetArray = IOHelper.newByteArrayOutput()) {
try (HOutput packetOutput = new HOutput(packetArray)) { try (HOutput packetOutput = new HOutput(packetArray)) {
packetOutput.writeUnsignedByte(0x4a); // Protocol version packetOutput.writeUnsignedByte(version.protocol); // Protocol version
writeUTF16String(packetOutput, address.getHostString()); // Server address writeUTF16String(packetOutput, address.getHostString()); // Server address
packetOutput.writeInt(address.getPort()); // Server port packetOutput.writeInt(address.getPort()); // Server port
} }
@ -113,7 +110,11 @@ private Result legacyPing(HInput input, HOutput output, boolean mc16) throws IOE
if (!magic.equals(LEGACY_PING_HOST_MAGIC)) if (!magic.equals(LEGACY_PING_HOST_MAGIC))
throw new IOException("Magic file mismatch: " + magic); throw new IOException("Magic file mismatch: " + magic);
int protocol = Integer.parseInt(splitted[1]); int protocol = Integer.parseInt(splitted[1]);
if (protocol != version.protocol)
throw new IOException("Protocol mismatch: " + protocol);
String clientVersion = splitted[2]; String clientVersion = splitted[2];
if (!clientVersion.equals(version.name))
throw new IOException(String.format("Version mismatch: '%s'", clientVersion));
int onlinePlayers = VerifyHelper.verifyInt(Integer.parseInt(splitted[4]), int onlinePlayers = VerifyHelper.verifyInt(Integer.parseInt(splitted[4]),
VerifyHelper.NOT_NEGATIVE, "onlinePlayers can't be < 0"); VerifyHelper.NOT_NEGATIVE, "onlinePlayers can't be < 0");
int maxPlayers = VerifyHelper.verifyInt(Integer.parseInt(splitted[5]), int maxPlayers = VerifyHelper.verifyInt(Integer.parseInt(splitted[5]),
@ -123,13 +124,13 @@ private Result legacyPing(HInput input, HOutput output, boolean mc16) throws IOE
return new Result(onlinePlayers, maxPlayers, response); return new Result(onlinePlayers, maxPlayers, response);
} }
private Result modernPing(HInput input, HOutput output, int protocol) throws IOException { private Result modernPing(HInput input, HOutput output) throws IOException {
// Prepare handshake packet // Prepare handshake packet
byte[] handshakePacket; byte[] handshakePacket;
try (ByteArrayOutputStream packetArray = IOHelper.newByteArrayOutput()) { try (ByteArrayOutputStream packetArray = IOHelper.newByteArrayOutput()) {
try (HOutput packetOutput = new HOutput(packetArray)) { try (HOutput packetOutput = new HOutput(packetArray)) {
packetOutput.writeVarInt(0x0); // Handshake packet ID packetOutput.writeVarInt(0x0); // Handshake packet ID
packetOutput.writeVarInt(protocol > 0 ? protocol : 0x4); // Protocol version packetOutput.writeVarInt(version.protocol); // Protocol version
packetOutput.writeString(address.getHostString(), 0); // Server address packetOutput.writeString(address.getHostString(), 0); // Server address
packetOutput.writeShort((short) address.getPort()); // Server port packetOutput.writeShort((short) address.getPort()); // Server port
packetOutput.writeVarInt(0x1); // Next state - status packetOutput.writeVarInt(0x1); // Next state - status

View file

@ -24,7 +24,7 @@ public String getUsageDescription() {
} }
@Override @Override
public void invoke(String... args) { public void invoke(String... args) throws Exception {
LogHelper.info("PublicKey: %s", Base64.getEncoder().encodeToString(engine.getClientPublicKey().getEncoded())); LogHelper.info("PublicKey: %s", Base64.getEncoder().encodeToString(engine.getClientPublicKey().getEncoded()));
} }
} }

View file

@ -23,7 +23,7 @@ public String getUsageDescription() {
} }
@Override @Override
public void invoke(String... args) { public void invoke(String... args) throws Exception {
for (LauncherModule module : LauncherEngine.modulesManager.getModules()) { for (LauncherModule module : LauncherEngine.modulesManager.getModules()) {
LauncherModuleInfo info = module.getModuleInfo(); LauncherModuleInfo info = module.getModuleInfo();
LauncherTrustManager.CheckClassResult checkStatus = module.getCheckResult(); LauncherTrustManager.CheckClassResult checkStatus = module.getCheckResult();

View file

@ -16,7 +16,7 @@ public String getUsageDescription() {
} }
@Override @Override
public void invoke(String... args) { public void invoke(String... args) throws Exception {
LogHelper.info("Your Hardware ID:"); LogHelper.info("Your Hardware ID:");
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
long currentTime; long currentTime;

View file

@ -0,0 +1,9 @@
package pro.gravit.launcher.guard;
import pro.gravit.launcher.client.ClientLauncherProcess;
public interface LauncherGuard {
String getName();
void applyGuardParams(ClientLauncherProcess process);
}

View file

@ -0,0 +1,15 @@
package pro.gravit.launcher.guard;
import pro.gravit.launcher.client.ClientLauncherProcess;
public class LauncherNoGuard implements LauncherGuard {
@Override
public String getName() {
return "noGuard";
}
@Override
public void applyGuardParams(ClientLauncherProcess process) {
//IGNORED
}
}

View file

@ -0,0 +1,40 @@
package pro.gravit.launcher.guard;
import pro.gravit.launcher.Launcher;
import pro.gravit.launcher.client.ClientLauncherProcess;
import pro.gravit.launcher.client.DirBridge;
import pro.gravit.utils.helper.JVMHelper;
import pro.gravit.utils.helper.UnpackHelper;
import java.io.IOException;
public class LauncherWrapperGuard implements LauncherGuard {
public LauncherWrapperGuard() {
try {
String wrapperName = JVMHelper.JVM_BITS == 64 ? "wrapper64.exe" : "wrapper32.exe";
String projectName = Launcher.getConfig().projectName;
String wrapperUnpackName = JVMHelper.JVM_BITS == 64 ? projectName.concat("64.exe") : projectName.concat("32.exe");
String antiInjectName = JVMHelper.JVM_BITS == 64 ? "AntiInject64.dll" : "AntiInject32.dll";
UnpackHelper.unpack(Launcher.getResourceURL(wrapperName, "guard"), DirBridge.getGuardDir().resolve(wrapperUnpackName));
UnpackHelper.unpack(Launcher.getResourceURL(antiInjectName, "guard"), DirBridge.getGuardDir().resolve(antiInjectName));
} catch (IOException e) {
throw new SecurityException(e);
}
}
@Override
public String getName() {
return "wrapper";
}
@Override
public void applyGuardParams(ClientLauncherProcess process) {
if (JVMHelper.OS_TYPE == JVMHelper.OS.MUSTDIE) {
String projectName = Launcher.getConfig().projectName;
String wrapperUnpackName = JVMHelper.JVM_BITS == 64 ? projectName.concat("64.exe") : projectName.concat("32.exe");
process.executeFile = DirBridge.getGuardDir().resolve(wrapperUnpackName);
process.useLegacyJavaClassPathProperty = true;
}
}
}

View file

@ -4,12 +4,12 @@
public class NoRuntimeProvider implements RuntimeProvider { public class NoRuntimeProvider implements RuntimeProvider {
@Override @Override
public void run(String[] args) { public void run(String[] args) throws Exception {
JOptionPane.showMessageDialog(null, "GUI часть лаунчера не найдена.\nС 5.1.0 вам необходимо самостоятельно установить модуль, отвечающий за GUI. Рантайм на JS более не поддерживается"); JOptionPane.showMessageDialog(null, "GUI часть лаунчера не найдена.\nС 5.1.0 вам необходимо самостоятельно установить модуль, отвечающий за GUI. Рантайм на JS более не поддерживается");
} }
@Override @Override
public void preLoad() { public void preLoad() throws Exception {
} }

View file

@ -1,9 +1,9 @@
package pro.gravit.launcher.gui; package pro.gravit.launcher.gui;
public interface RuntimeProvider { public interface RuntimeProvider {
void run(String[] args); void run(String[] args) throws Exception;
void preLoad(); void preLoad() throws Exception;
void init(boolean clientInstance); void init(boolean clientInstance);
} }

View file

@ -115,6 +115,10 @@ private final class RegisterFileVisitor extends SimpleFileVisitor<Path> {
@Override @Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
FileVisitResult result = super.preVisitDirectory(dir, attrs); FileVisitResult result = super.preVisitDirectory(dir, attrs);
if (DirWatcher.this.dir.equals(dir)) {
dir.register(service, KINDS);
return result;
}
// Maybe it's unnecessary to go deeper // Maybe it's unnecessary to go deeper
//if (matcher != null && !matcher.shouldVerify(path)) { //if (matcher != null && !matcher.shouldVerify(path)) {

Some files were not shown because too many files have changed in this diff Show more