mirror of
https://github.com/GravitLauncher/Launcher
synced 2024-12-23 00:51:01 +03:00
[REFRACTOR] Удалены все запросы и большинство ответов по протоколу сашка
This commit is contained in:
parent
d805fb7515
commit
dbb07dee79
46 changed files with 39 additions and 1506 deletions
|
@ -1,6 +1,6 @@
|
|||
package ru.gravit.launchserver.auth.protect;
|
||||
|
||||
import ru.gravit.launchserver.response.auth.AuthResponse;
|
||||
import ru.gravit.launchserver.socket.websocket.json.auth.AuthResponse;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
|
||||
public class NoProtectHandler extends ProtectHandler {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package ru.gravit.launchserver.auth.protect;
|
||||
|
||||
import ru.gravit.launchserver.response.auth.AuthResponse;
|
||||
import ru.gravit.launchserver.socket.websocket.json.auth.AuthResponse;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.util.Map;
|
||||
|
|
|
@ -200,7 +200,7 @@ public Path process(Path inputJar) throws IOException {
|
|||
byte[] launcherConfigBytes;
|
||||
try (ByteArrayOutputStream configArray = IOHelper.newByteArrayOutput()) {
|
||||
try (HOutput configOutput = new HOutput(configArray)) {
|
||||
new LauncherConfig(server.config.getAddress(), server.config.port, server.publicKey, runtime)
|
||||
new LauncherConfig(server.config.netty.address, server.publicKey, runtime)
|
||||
.write(configOutput);
|
||||
}
|
||||
launcherConfigBytes = configArray.toByteArray();
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import ru.gravit.launchserver.response.auth.AuthResponse;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.launchserver.socket.websocket.json.auth.AuthResponse;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package ru.gravit.launchserver.manangers.hook;
|
||||
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.response.auth.AuthResponse;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.launchserver.socket.websocket.json.auth.AuthResponse;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
|
|
@ -5,11 +5,6 @@
|
|||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.admin.ExecCommandResponse;
|
||||
import ru.gravit.launchserver.response.auth.*;
|
||||
import ru.gravit.launchserver.response.profile.BatchProfileByUsernameResponse;
|
||||
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
|
||||
import ru.gravit.launchserver.response.profile.ProfileByUsernameResponse;
|
||||
import ru.gravit.launchserver.response.update.*;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
@ -37,23 +32,8 @@ public static void registerResponse(int type, Factory<?> factory) {
|
|||
|
||||
public static void registerResponses() {
|
||||
registerResponse(RequestType.PING.getNumber(), PingResponse::new);
|
||||
registerResponse(RequestType.AUTH.getNumber(), AuthResponse::new);
|
||||
registerResponse(RequestType.CHECK_SERVER.getNumber(), CheckServerResponse::new);
|
||||
registerResponse(RequestType.JOIN_SERVER.getNumber(), JoinServerResponse::new);
|
||||
|
||||
registerResponse(RequestType.BATCH_PROFILE_BY_USERNAME.getNumber(), BatchProfileByUsernameResponse::new);
|
||||
registerResponse(RequestType.PROFILE_BY_USERNAME.getNumber(), ProfileByUsernameResponse::new);
|
||||
registerResponse(RequestType.PROFILE_BY_UUID.getNumber(), ProfileByUUIDResponse::new);
|
||||
|
||||
registerResponse(RequestType.LEGACYLAUNCHER.getNumber(), LegacyLauncherResponse::new);
|
||||
registerResponse(RequestType.LAUNCHER.getNumber(), LauncherResponse::new);
|
||||
registerResponse(RequestType.UPDATE_LIST.getNumber(), UpdateListResponse::new);
|
||||
registerResponse(RequestType.UPDATE.getNumber(), UpdateResponse::new);
|
||||
registerResponse(RequestType.PROFILES.getNumber(), ProfilesResponse::new);
|
||||
registerResponse(RequestType.SERVERAUTH.getNumber(), AuthServerResponse::new);
|
||||
registerResponse(RequestType.SETPROFILE.getNumber(), SetProfileResponse::new);
|
||||
registerResponse(RequestType.CHANGESERVER.getNumber(), ChangeServerResponse::new);
|
||||
registerResponse(RequestType.EXECCOMMAND.getNumber(), ExecCommandResponse::new);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,42 +0,0 @@
|
|||
package ru.gravit.launchserver.response.admin;
|
||||
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ExecCommandResponse extends Response {
|
||||
public ExecCommandResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws Exception {
|
||||
Client clientData = server.sessionManager.getClient(session);
|
||||
if (!clientData.isAuth || !clientData.permissions.canAdmin || !server.config.enableRcon)
|
||||
requestError("Access denied");
|
||||
writeNoError(output);
|
||||
String cmd = input.readString(SerializeLimits.MAX_COMMAND);
|
||||
LogHelper.OutputEnity loutput = new LogHelper.OutputEnity(message -> {
|
||||
try {
|
||||
output.writeBoolean(true);
|
||||
output.writeString(message, SerializeLimits.MAX_COMMAND);
|
||||
} catch (IOException e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}, LogHelper.OutputTypes.PLAIN);
|
||||
LogHelper.addOutput(loutput);
|
||||
try {
|
||||
server.commandHandler.eval(cmd, false);
|
||||
output.writeBoolean(false);
|
||||
} finally {
|
||||
LogHelper.removeOutput(loutput);
|
||||
}
|
||||
writeNoError(output);
|
||||
}
|
||||
}
|
|
@ -1,154 +0,0 @@
|
|||
package ru.gravit.launchserver.response.auth;
|
||||
|
||||
import ru.gravit.launcher.OshiHWID;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.AuthProviderPair;
|
||||
import ru.gravit.launchserver.auth.hwid.HWIDException;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class AuthResponse extends Response {
|
||||
private static String echo(int length) {
|
||||
char[] chars = new char[length];
|
||||
Arrays.fill(chars, '*');
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
public AuthResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
public static class AuthContext {
|
||||
public AuthContext(long session, String login, int password_lenght, String customText, String client, String hwid, String ip, boolean isServerAuth) {
|
||||
this.session = session;
|
||||
this.login = login;
|
||||
this.password_lenght = password_lenght;
|
||||
this.customText = customText;
|
||||
this.client = client;
|
||||
this.hwid = hwid;
|
||||
this.ip = ip;
|
||||
this.isServerAuth = isServerAuth;
|
||||
}
|
||||
|
||||
public long session;
|
||||
public String login;
|
||||
public int password_lenght; //Use AuthProvider for get password
|
||||
public String client;
|
||||
public String hwid;
|
||||
public String customText;
|
||||
public String ip;
|
||||
public boolean isServerAuth;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws Exception {
|
||||
String login = input.readString(SerializeLimits.MAX_LOGIN);
|
||||
boolean isClient = input.readBoolean();
|
||||
String client = null;
|
||||
if (isClient)
|
||||
client = input.readString(SerializeLimits.MAX_CLIENT);
|
||||
String auth_id = input.readString(SerializeLimits.MAX_QUEUE_SIZE);
|
||||
String hwid_str = input.readString(SerializeLimits.MAX_HWID_STR);
|
||||
byte[] encryptedPassword = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH);
|
||||
String customText = input.readString(SerializeLimits.MAX_CUSTOM_TEXT);
|
||||
// Decrypt password
|
||||
String password;
|
||||
try {
|
||||
password = IOHelper.decode(SecurityHelper.newRSADecryptCipher(server.privateKey).
|
||||
doFinal(encryptedPassword));
|
||||
} catch (IllegalBlockSizeException | BadPaddingException ignored) {
|
||||
requestError("Password decryption error");
|
||||
return;
|
||||
}
|
||||
|
||||
// Authenticate
|
||||
debug("Login: '%s', Password: '%s'", login, echo(password.length()));
|
||||
AuthProviderResult result;
|
||||
AuthProviderPair pair;
|
||||
if (auth_id.isEmpty()) pair = server.config.getAuthProviderPair();
|
||||
else pair = server.config.getAuthProviderPair(auth_id);
|
||||
if (pair == null) requestError("Auth type not found");
|
||||
AuthProvider provider = pair.provider;
|
||||
clientData.type = Client.Type.USER;
|
||||
AuthContext context = new AuthContext(session, login, password.length(), customText, client, hwid_str, ip, false);
|
||||
try {
|
||||
server.authHookManager.preHook(context, clientData);
|
||||
if (!clientData.checkSign) {
|
||||
throw new AuthException("You must using checkLauncher");
|
||||
}
|
||||
provider.preAuth(login, password, customText, ip);
|
||||
result = provider.auth(login, password, ip);
|
||||
if (!VerifyHelper.isValidUsername(result.username)) {
|
||||
AuthProvider.authError(String.format("Illegal result: '%s'", result.username));
|
||||
return;
|
||||
}
|
||||
if (isClient) {
|
||||
Collection<ClientProfile> profiles = server.getProfiles();
|
||||
for (ClientProfile p : profiles) {
|
||||
if (p.getTitle().equals(client)) {
|
||||
if (!p.isWhitelistContains(login)) {
|
||||
throw new AuthException(server.config.whitelistRejectString);
|
||||
}
|
||||
clientData.profile = p;
|
||||
}
|
||||
}
|
||||
if (clientData.profile == null) {
|
||||
throw new AuthException("Your profile is not found");
|
||||
}
|
||||
}
|
||||
server.config.hwidHandler.check(OshiHWID.gson.fromJson(hwid_str, OshiHWID.class), result.username);
|
||||
server.authHookManager.postHook(context, clientData);
|
||||
} catch (AuthException | HWIDException e) {
|
||||
if (e.getMessage() == null) LogHelper.error(e);
|
||||
requestError(e.getMessage());
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
requestError("Internal auth provider error");
|
||||
return;
|
||||
}
|
||||
debug("Auth: '%s' -> '%s', '%s'", login, result.username, result.accessToken);
|
||||
clientData.isAuth = true;
|
||||
clientData.permissions = result.permissions;
|
||||
clientData.username = result.username;
|
||||
clientData.auth_id = auth_id;
|
||||
clientData.updateAuth();
|
||||
// Authenticate on server (and get UUID)
|
||||
UUID uuid;
|
||||
try {
|
||||
uuid = pair.handler.auth(result);
|
||||
} catch (AuthException e) {
|
||||
requestError(e.getMessage());
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
requestError("Internal auth handler error");
|
||||
return;
|
||||
}
|
||||
String protectToken = server.config.protectHandler.generateSecureToken(context);
|
||||
writeNoError(output);
|
||||
// Write profile and UUID
|
||||
ProfileByUUIDResponse.getProfile(server, uuid, result.username, client, clientData.auth.textureProvider).write(output);
|
||||
output.writeASCII(result.accessToken, -SecurityHelper.TOKEN_STRING_LENGTH);
|
||||
clientData.permissions.write(output);
|
||||
output.writeString(protectToken, SerializeLimits.MAX_CUSTOM_TEXT);
|
||||
}
|
||||
}
|
|
@ -1,98 +0,0 @@
|
|||
package ru.gravit.launchserver.response.auth;
|
||||
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.auth.AuthProviderPair;
|
||||
import ru.gravit.launchserver.auth.hwid.HWIDException;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import javax.crypto.BadPaddingException;
|
||||
import javax.crypto.IllegalBlockSizeException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
public final class AuthServerResponse extends Response {
|
||||
private static String echo(int length) {
|
||||
char[] chars = new char[length];
|
||||
Arrays.fill(chars, '*');
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
public AuthServerResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws Exception {
|
||||
String login = input.readString(SerializeLimits.MAX_LOGIN);
|
||||
String client = input.readString(SerializeLimits.MAX_CLIENT);
|
||||
String auth_id = input.readString(SerializeLimits.MAX_QUEUE_SIZE);
|
||||
byte[] encryptedPassword = input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH);
|
||||
// Decrypt password
|
||||
String password;
|
||||
try {
|
||||
password = IOHelper.decode(SecurityHelper.newRSADecryptCipher(server.privateKey).
|
||||
doFinal(encryptedPassword));
|
||||
} catch (IllegalBlockSizeException | BadPaddingException ignored) {
|
||||
requestError("ServerPassword decryption error");
|
||||
return;
|
||||
}
|
||||
// Authenticate
|
||||
debug("ServerLogin: '%s', Password: '%s'", login, echo(password.length()));
|
||||
AuthProviderResult result;
|
||||
AuthProviderPair pair;
|
||||
if (auth_id.isEmpty()) pair = server.config.getAuthProviderPair();
|
||||
else pair = server.config.getAuthProviderPair(auth_id);
|
||||
if (pair == null) requestError("Auth type not found");
|
||||
AuthProvider provider = pair.provider;
|
||||
AuthResponse.AuthContext context = new AuthResponse.AuthContext(session, login, password.length(), null, client, null, ip, true);
|
||||
try {
|
||||
server.authHookManager.preHook(context, clientData);
|
||||
result = provider.auth(login, password, ip);
|
||||
if (!VerifyHelper.isValidUsername(result.username)) {
|
||||
AuthProvider.authError(String.format("Illegal result: '%s'", result.username));
|
||||
return;
|
||||
}
|
||||
Collection<ClientProfile> profiles = server.getProfiles();
|
||||
for (ClientProfile p : profiles) {
|
||||
if (p.getTitle().equals(client)) {
|
||||
clientData.profile = p;
|
||||
}
|
||||
}
|
||||
if (clientData.profile == null) {
|
||||
throw new AuthException("Your profile is not found");
|
||||
}
|
||||
clientData.permissions = server.config.permissionsHandler.getPermissions(login);
|
||||
if (!clientData.permissions.canServer) {
|
||||
throw new AuthException("Your account cannot be a server");
|
||||
}
|
||||
clientData.type = Client.Type.SERVER;
|
||||
clientData.username = result.username;
|
||||
server.authHookManager.postHook(context, clientData);
|
||||
} catch (AuthException | HWIDException e) {
|
||||
requestError(e.getMessage());
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
requestError("Internal auth provider error");
|
||||
return;
|
||||
}
|
||||
debug("ServerAuth: '%s' -> '%s', '%s'", login, result.username, result.accessToken);
|
||||
clientData.isAuth = true;
|
||||
clientData.auth_id = auth_id;
|
||||
clientData.updateAuth();
|
||||
writeNoError(output);
|
||||
clientData.permissions.write(output);
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package ru.gravit.launchserver.response.auth;
|
||||
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
|
||||
public class ChangeServerResponse extends Response {
|
||||
public static boolean needChange = false;
|
||||
public static String address;
|
||||
public static int port;
|
||||
|
||||
public ChangeServerResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws Exception {
|
||||
writeNoError(output);
|
||||
output.writeBoolean(needChange);
|
||||
//if true
|
||||
if (needChange) {
|
||||
output.writeString(address, 255);
|
||||
output.writeInt(port);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,53 +0,0 @@
|
|||
package ru.gravit.launchserver.response.auth;
|
||||
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class CheckServerResponse extends Response {
|
||||
|
||||
public CheckServerResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws IOException {
|
||||
String username = VerifyHelper.verifyUsername(input.readString(SerializeLimits.MAX_LOGIN));
|
||||
String serverID = VerifyHelper.verifyServerID(input.readASCII(41)); // With minus sign
|
||||
String client = input.readString(SerializeLimits.MAX_CLIENT);
|
||||
debug("Username: %s, Server ID: %s", username, serverID);
|
||||
if (!clientData.isAuth || clientData.type != Client.Type.SERVER) {
|
||||
requestError("Access denied");
|
||||
return;
|
||||
}
|
||||
// Try check server with auth handler
|
||||
UUID uuid;
|
||||
try {
|
||||
server.authHookManager.checkServerHook(username, serverID);
|
||||
uuid = clientData.auth.handler.checkServer(username, serverID);
|
||||
} catch (AuthException e) {
|
||||
requestError(e.getMessage());
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
requestError("Internal auth handler error");
|
||||
return;
|
||||
}
|
||||
writeNoError(output);
|
||||
|
||||
// Write profile and UUID
|
||||
output.writeBoolean(uuid != null);
|
||||
if (uuid != null)
|
||||
ProfileByUUIDResponse.getProfile(server, uuid, username, client, clientData.auth.textureProvider).write(output);
|
||||
}
|
||||
}
|
|
@ -1,50 +0,0 @@
|
|||
package ru.gravit.launchserver.response.auth;
|
||||
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class JoinServerResponse extends Response {
|
||||
|
||||
public JoinServerResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws IOException {
|
||||
String username = VerifyHelper.verifyUsername(input.readString(SerializeLimits.MAX_LOGIN));
|
||||
String accessToken = SecurityHelper.verifyToken(input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH));
|
||||
String serverID = VerifyHelper.verifyServerID(input.readASCII(SerializeLimits.MAX_SERVERID)); // With minus sign
|
||||
if (!clientData.isAuth || clientData.type != Client.Type.USER) {
|
||||
requestError("Access denied");
|
||||
return;
|
||||
}
|
||||
// Try join server with auth handler
|
||||
debug("Username: '%s', Access token: %s, Server ID: %s", username, accessToken, serverID);
|
||||
boolean success;
|
||||
try {
|
||||
server.authHookManager.joinServerHook(username, accessToken, serverID);
|
||||
success = clientData.auth.handler.joinServer(username, accessToken, serverID);
|
||||
} catch (AuthException e) {
|
||||
requestError(e.getMessage());
|
||||
return;
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
requestError("Internal auth handler error");
|
||||
return;
|
||||
}
|
||||
writeNoError(output);
|
||||
|
||||
// Write response
|
||||
output.writeBoolean(success);
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
package ru.gravit.launchserver.response.auth;
|
||||
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public class SetProfileResponse extends Response {
|
||||
public SetProfileResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws Exception {
|
||||
String client = input.readString(SerializeLimits.MAX_CLIENT);
|
||||
if (!clientData.isAuth) requestError("You not auth");
|
||||
Collection<ClientProfile> profiles = server.getProfiles();
|
||||
for (ClientProfile p : profiles) {
|
||||
if (p.getTitle().equals(client)) {
|
||||
if (!p.isWhitelistContains(clientData.username)) {
|
||||
requestError(server.config.whitelistRejectString);
|
||||
return;
|
||||
}
|
||||
clientData.profile = p;
|
||||
writeNoError(output);
|
||||
output.writeBoolean(true);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
package ru.gravit.launchserver.response.profile;
|
||||
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
|
||||
public final class BatchProfileByUsernameResponse extends Response {
|
||||
|
||||
public BatchProfileByUsernameResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws IOException {
|
||||
int length = input.readLength(SerializeLimits.MAX_BATCH_SIZE);
|
||||
String[] usernames = new String[length];
|
||||
String[] clients = new String[length];
|
||||
for (int i = 0; i < usernames.length; i++) {
|
||||
usernames[i] = VerifyHelper.verifyUsername(input.readString(64));
|
||||
clients[i] = input.readString(SerializeLimits.MAX_CLIENT);
|
||||
}
|
||||
debug("Usernames: " + Arrays.toString(usernames));
|
||||
|
||||
// Respond with profiles array
|
||||
for (int i = 0; i < usernames.length; i++)
|
||||
ProfileByUsernameResponse.writeProfile(server, output, usernames[i], clients[i], clientData.auth);
|
||||
}
|
||||
}
|
|
@ -1,62 +0,0 @@
|
|||
package ru.gravit.launchserver.response.profile;
|
||||
|
||||
import ru.gravit.launcher.profiles.PlayerProfile;
|
||||
import ru.gravit.launcher.profiles.Texture;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.launchserver.texture.TextureProvider;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class ProfileByUUIDResponse extends Response {
|
||||
|
||||
public static PlayerProfile getProfile(LaunchServer server, UUID uuid, String username, String client, TextureProvider textureProvider) {
|
||||
// Get skin texture
|
||||
Texture skin;
|
||||
try {
|
||||
skin = textureProvider.getSkinTexture(uuid, username, client);
|
||||
} catch (IOException e) {
|
||||
LogHelper.error(new IOException(String.format("Can't get skin texture: '%s'", username), e));
|
||||
skin = null;
|
||||
}
|
||||
|
||||
// Get cloak texture
|
||||
Texture cloak;
|
||||
try {
|
||||
cloak = textureProvider.getCloakTexture(uuid, username, client);
|
||||
} catch (IOException e) {
|
||||
LogHelper.error(new IOException(String.format("Can't get cloak texture: '%s'", username), e));
|
||||
cloak = null;
|
||||
}
|
||||
|
||||
// Return combined profile
|
||||
return new PlayerProfile(uuid, username, skin, cloak);
|
||||
}
|
||||
|
||||
public ProfileByUUIDResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws IOException {
|
||||
UUID uuid = input.readUUID();
|
||||
debug("UUID: " + uuid);
|
||||
String client = input.readString(SerializeLimits.MAX_CLIENT);
|
||||
// Verify has such profile
|
||||
String username = clientData.auth.handler.uuidToUsername(uuid);
|
||||
if (username == null) {
|
||||
output.writeBoolean(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write profile
|
||||
output.writeBoolean(true);
|
||||
getProfile(server, uuid, username, client, clientData.auth.textureProvider).write(output);
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package ru.gravit.launchserver.response.profile;
|
||||
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthProviderPair;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
|
||||
public final class ProfileByUsernameResponse extends Response {
|
||||
|
||||
public static void writeProfile(LaunchServer server, HOutput output, String username, String client, AuthProviderPair pair) throws IOException {
|
||||
UUID uuid = pair.handler.usernameToUUID(username);
|
||||
if (uuid == null) {
|
||||
output.writeBoolean(false);
|
||||
return;
|
||||
}
|
||||
|
||||
// Write profile
|
||||
output.writeBoolean(true);
|
||||
ProfileByUUIDResponse.getProfile(server, uuid, username, client, pair.textureProvider).write(output);
|
||||
}
|
||||
|
||||
public ProfileByUsernameResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws IOException {
|
||||
String username = VerifyHelper.verifyUsername(input.readString(64));
|
||||
debug("Username: " + username);
|
||||
String client = input.readString(SerializeLimits.MAX_CLIENT);
|
||||
// Write response
|
||||
writeProfile(server, output, username, client, clientData.auth);
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
package ru.gravit.launchserver.response.update;
|
||||
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
||||
public final class ProfilesResponse extends Response {
|
||||
|
||||
public ProfilesResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws IOException {
|
||||
// Resolve launcher binary
|
||||
input.readBoolean();
|
||||
if (clientData.type == Client.Type.USER && !clientData.checkSign) {
|
||||
LogHelper.warning("User session: %d ip %s try get profiles", session, ip);
|
||||
requestError("Access denied");
|
||||
return;
|
||||
}
|
||||
writeNoError(output);
|
||||
Collection<ClientProfile> profiles = server.getProfiles();
|
||||
output.writeLength(profiles.size(), 0);
|
||||
for (ClientProfile profile : profiles) {
|
||||
LogHelper.debug("Writted profile: %s", profile.getTitle());
|
||||
output.writeString(Launcher.gson.toJson(profile), 0);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
package ru.gravit.launchserver.response.update;
|
||||
|
||||
import ru.gravit.launcher.hasher.HashedDir;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
public final class UpdateListResponse extends Response {
|
||||
|
||||
public UpdateListResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws Exception {
|
||||
Set<Entry<String, SignedObjectHolder<HashedDir>>> updateDirs = server.getUpdateDirs();
|
||||
// Write all update dirs names
|
||||
output.writeLength(updateDirs.size(), 0);
|
||||
for (Entry<String, SignedObjectHolder<HashedDir>> entry : updateDirs)
|
||||
output.writeString(entry.getKey(), 255);
|
||||
}
|
||||
}
|
|
@ -1,140 +0,0 @@
|
|||
package ru.gravit.launchserver.response.update;
|
||||
|
||||
import ru.gravit.launcher.hasher.HashedDir;
|
||||
import ru.gravit.launcher.hasher.HashedEntry;
|
||||
import ru.gravit.launcher.hasher.HashedEntry.Type;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.request.UpdateAction;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.launcher.serialize.signed.SignedObjectHolder;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.response.Response;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Deque;
|
||||
import java.util.LinkedList;
|
||||
import java.util.zip.DeflaterOutputStream;
|
||||
|
||||
public final class UpdateResponse extends Response {
|
||||
|
||||
public UpdateResponse(LaunchServer server, long session, HInput input, HOutput output, String ip, Client clientData) {
|
||||
super(server, session, input, output, ip, clientData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reply() throws IOException {
|
||||
// Read update dir name
|
||||
String updateDirName = IOHelper.verifyFileName(input.readString(255));
|
||||
SignedObjectHolder<HashedDir> hdir = server.getUpdateDir(updateDirName);
|
||||
if (hdir == null) {
|
||||
requestError(String.format("Unknown update dir: %s", updateDirName));
|
||||
return;
|
||||
}
|
||||
if (!clientData.isAuth || clientData.type != Client.Type.USER || clientData.profile == null) {
|
||||
requestError("Access denied");
|
||||
return;
|
||||
}
|
||||
if (!clientData.permissions.canAdmin) {
|
||||
for (ClientProfile p : server.getProfiles()) {
|
||||
if (!clientData.profile.getTitle().equals(p.getTitle())) continue;
|
||||
if (!p.isWhitelistContains(clientData.username)) {
|
||||
requestError("You don't download this folder");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writeNoError(output);
|
||||
|
||||
// Write update hdir
|
||||
debug("Update dir: '%s'", updateDirName);
|
||||
hdir.write(output);
|
||||
output.writeBoolean(server.config.compress);
|
||||
output.flush();
|
||||
|
||||
// Prepare variables for actions queue
|
||||
Path dir = server.updatesDir.resolve(updateDirName);
|
||||
Deque<HashedDir> dirStack = new LinkedList<>();
|
||||
dirStack.add(hdir.object);
|
||||
|
||||
// Perform update
|
||||
// noinspection IOResourceOpenedButNotSafelyClosed
|
||||
OutputStream fileOutput = server.config.compress ? new DeflaterOutputStream(output.stream, IOHelper.newDeflater(), IOHelper.BUFFER_SIZE, true) : output.stream;
|
||||
UpdateAction[] actionsSlice = new UpdateAction[SerializeLimits.MAX_QUEUE_SIZE];
|
||||
loop:
|
||||
while (true) {
|
||||
// Read actions slice
|
||||
int length = input.readLength(actionsSlice.length);
|
||||
for (int i = 0; i < length; i++)
|
||||
actionsSlice[i] = new UpdateAction(input);
|
||||
|
||||
// Perform actions
|
||||
for (int i = 0; i < length; i++) {
|
||||
UpdateAction action = actionsSlice[i];
|
||||
switch (action.type) {
|
||||
case CD:
|
||||
debug("CD '%s'", action.name);
|
||||
|
||||
// Get hashed dir (for validation)
|
||||
HashedEntry hSubdir = dirStack.getLast().getEntry(action.name);
|
||||
if (hSubdir == null || hSubdir.getType() != Type.DIR)
|
||||
throw new IOException("Unknown hashed dir: " + action.name);
|
||||
dirStack.add((HashedDir) hSubdir);
|
||||
|
||||
// Resolve dir
|
||||
dir = dir.resolve(action.name);
|
||||
break;
|
||||
case GET:
|
||||
debug("GET '%s'", action.name);
|
||||
|
||||
// Get hashed file (for validation)
|
||||
HashedEntry hFile = dirStack.getLast().getEntry(action.name);
|
||||
if (hFile == null || hFile.getType() != Type.FILE)
|
||||
throw new IOException("Unknown hashed file: " + action.name);
|
||||
|
||||
// Resolve and write file
|
||||
Path file = dir.resolve(action.name);
|
||||
if (IOHelper.readAttributes(file).size() != hFile.size()) {
|
||||
fileOutput.write(0x0);
|
||||
fileOutput.flush();
|
||||
throw new IOException("Unknown hashed file: " + action.name);
|
||||
}
|
||||
fileOutput.write(0xFF);
|
||||
try (InputStream fileInput = IOHelper.newInput(file)) {
|
||||
IOHelper.transfer(fileInput, fileOutput);
|
||||
}
|
||||
break;
|
||||
case CD_BACK:
|
||||
debug("CD ..");
|
||||
|
||||
// Remove from hashed dir stack
|
||||
dirStack.removeLast();
|
||||
if (dirStack.isEmpty())
|
||||
throw new IOException("Empty hDir stack");
|
||||
|
||||
// Get parent
|
||||
dir = dir.getParent();
|
||||
break;
|
||||
case FINISH:
|
||||
break loop;
|
||||
default:
|
||||
throw new AssertionError(String.format("Unsupported action type: '%s'", action.type.name()));
|
||||
}
|
||||
}
|
||||
|
||||
// Flush all actions
|
||||
fileOutput.flush();
|
||||
}
|
||||
|
||||
// So we've updated :)
|
||||
if (fileOutput instanceof DeflaterOutputStream)
|
||||
((DeflaterOutputStream) fileOutput).finish();
|
||||
}
|
||||
}
|
|
@ -11,10 +11,10 @@
|
|||
import ru.gravit.launchserver.auth.hwid.HWIDException;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProvider;
|
||||
import ru.gravit.launchserver.auth.provider.AuthProviderResult;
|
||||
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.launchserver.socket.websocket.WebSocketService;
|
||||
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
|
||||
import ru.gravit.launchserver.socket.websocket.json.profile.ProfileByUUIDResponse;
|
||||
import ru.gravit.utils.helper.IOHelper;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
|
@ -84,7 +84,7 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
|
|||
AuthProviderPair pair;
|
||||
if (auth_id.isEmpty()) pair = LaunchServer.server.config.getAuthProviderPair();
|
||||
else pair = LaunchServer.server.config.getAuthProviderPair(auth_id);
|
||||
ru.gravit.launchserver.response.auth.AuthResponse.AuthContext context = new ru.gravit.launchserver.response.auth.AuthResponse.AuthContext(0, login, password.length(), customText, client, ip, null, false);
|
||||
AuthContext context = new AuthContext(0, login, password.length(), customText, client, ip, null, false);
|
||||
AuthProvider provider = pair.provider;
|
||||
LaunchServer.server.authHookManager.preHook(context, clientData);
|
||||
provider.preAuth(login, password, customText, ip);
|
||||
|
@ -128,5 +128,25 @@ public void execute(WebSocketService service, ChannelHandlerContext ctx, Client
|
|||
service.sendObject(ctx, new ErrorRequestEvent(e.getMessage()));
|
||||
}
|
||||
}
|
||||
public static class AuthContext {
|
||||
public AuthContext(long session, String login, int password_lenght, String customText, String client, String hwid, String ip, boolean isServerAuth) {
|
||||
this.session = session;
|
||||
this.login = login;
|
||||
this.password_lenght = password_lenght;
|
||||
this.customText = customText;
|
||||
this.client = client;
|
||||
this.hwid = hwid;
|
||||
this.ip = ip;
|
||||
this.isServerAuth = isServerAuth;
|
||||
}
|
||||
|
||||
public long session;
|
||||
public String login;
|
||||
public int password_lenght; //Use AuthProvider for get password
|
||||
public String client;
|
||||
public String hwid;
|
||||
public String customText;
|
||||
public String ip;
|
||||
public boolean isServerAuth;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,10 +5,10 @@
|
|||
import ru.gravit.launcher.events.request.ErrorRequestEvent;
|
||||
import ru.gravit.launchserver.LaunchServer;
|
||||
import ru.gravit.launchserver.auth.AuthException;
|
||||
import ru.gravit.launchserver.response.profile.ProfileByUUIDResponse;
|
||||
import ru.gravit.launchserver.socket.Client;
|
||||
import ru.gravit.launchserver.socket.websocket.WebSocketService;
|
||||
import ru.gravit.launchserver.socket.websocket.json.JsonResponseInterface;
|
||||
import ru.gravit.launchserver.socket.websocket.json.profile.ProfileByUUIDResponse;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public class CheckServerResponse implements JsonResponseInterface {
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package ru.gravit.launchserver.console;
|
||||
|
||||
import ru.gravit.launcher.request.admin.ExecCommandRequest;
|
||||
import ru.gravit.utils.command.JLineCommandHandler;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
@ -13,11 +11,5 @@ public RemoteJLineCommandHandler() throws IOException {
|
|||
@Override
|
||||
public void eval(String line, boolean bell) {
|
||||
if (line.equals("exit")) System.exit(0);
|
||||
ExecCommandRequest request = new ExecCommandRequest(System.out::println, line);
|
||||
try {
|
||||
request.request();
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
package ru.gravit.launchserver.console;
|
||||
|
||||
import ru.gravit.launcher.request.admin.ExecCommandRequest;
|
||||
import ru.gravit.utils.command.StdCommandHandler;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public class RemoteStdCommandHandler extends StdCommandHandler {
|
||||
public RemoteStdCommandHandler(boolean readCommands) {
|
||||
|
@ -12,11 +10,5 @@ public RemoteStdCommandHandler(boolean readCommands) {
|
|||
@Override
|
||||
public void eval(String line, boolean bell) {
|
||||
if (line.equals("exit")) System.exit(0);
|
||||
ExecCommandRequest request = new ExecCommandRequest(System.out::println, line);
|
||||
try {
|
||||
request.request();
|
||||
} catch (Exception e) {
|
||||
LogHelper.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -63,7 +63,6 @@ public static void addLauncherClassBindings(Map<String, Object> bindings) {
|
|||
bindings.put("RequestClass", Request.class);
|
||||
bindings.put("RequestTypeClass", RequestType.class);
|
||||
bindings.put("RequestExceptionClass", RequestException.class);
|
||||
bindings.put("CustomRequestClass", CustomRequest.class);
|
||||
bindings.put("PingRequestClass", PingRequest.class);
|
||||
bindings.put("AuthRequestClass", AuthRequest.class);
|
||||
bindings.put("JoinServerRequestClass", JoinServerRequest.class);
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
package ru.gravit.launcher.request;
|
||||
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.LauncherConfig;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
public abstract class CustomRequest<T> extends Request<T> {
|
||||
@LauncherAPI
|
||||
public CustomRequest() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public CustomRequest(LauncherConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public abstract String getName();
|
||||
|
||||
@Override
|
||||
public final Integer getLegacyType() {
|
||||
return 255;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final T requestDo(HInput input, HOutput output) throws Exception {
|
||||
output.writeASCII(VerifyHelper.verifyIDName(getName()), 255);
|
||||
output.flush();
|
||||
|
||||
// Custom request redirect
|
||||
return requestDoCustom(input, output);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
protected abstract T requestDoCustom(HInput input, HOutput output);
|
||||
}
|
|
@ -19,17 +19,4 @@ public PingRequest() {
|
|||
public PingRequest(LauncherConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.PING.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Void requestDo(HInput input, HOutput output) throws IOException {
|
||||
byte pong = (byte) input.readUnsignedByte();
|
||||
if (pong != SerializeLimits.EXPECTED_BYTE)
|
||||
throw new IOException("Illegal ping response: " + pong);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -43,9 +43,6 @@ protected Request(LauncherConfig config) {
|
|||
this.config = config == null ? Launcher.getConfig() : config;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public abstract Integer getLegacyType();
|
||||
|
||||
@LauncherAPI
|
||||
protected final void readError(HInput input) throws IOException {
|
||||
String error = input.readString(0);
|
||||
|
@ -57,39 +54,11 @@ protected final void readError(HInput input) throws IOException {
|
|||
public R request() throws Exception {
|
||||
if (!started.compareAndSet(false, true))
|
||||
throw new IllegalStateException("Request already started");
|
||||
R wsResult = null;
|
||||
if (config.isNettyEnabled)
|
||||
wsResult = requestWebSockets();
|
||||
if (wsResult != null) return wsResult;
|
||||
// Make request to LaunchServer
|
||||
try (Socket socket = IOHelper.newSocket()) {
|
||||
socket.connect(IOHelper.resolve(config.address));
|
||||
try (HInput input = new HInput(socket.getInputStream());
|
||||
HOutput output = new HOutput(socket.getOutputStream())) {
|
||||
writeHandshake(input, output);
|
||||
return requestDo(input, output);
|
||||
}
|
||||
}
|
||||
return requestWebSockets();
|
||||
}
|
||||
|
||||
protected R requestWebSockets() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
protected abstract R requestDo(HInput input, HOutput output) throws Exception;
|
||||
|
||||
private void writeHandshake(HInput input, HOutput output) throws IOException {
|
||||
// Write handshake
|
||||
output.writeInt(Launcher.PROTOCOL_MAGIC);
|
||||
output.writeBigInteger(config.publicKey.getModulus(), SecurityHelper.RSA_KEY_LENGTH + 1);
|
||||
output.writeLong(session);
|
||||
output.writeVarInt(getLegacyType());
|
||||
output.flush();
|
||||
|
||||
// Verify is accepted
|
||||
if (!input.readBoolean())
|
||||
requestError("Serverside not accepted this connection");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,39 +0,0 @@
|
|||
package ru.gravit.launcher.request.admin;
|
||||
|
||||
import ru.gravit.launcher.request.Request;
|
||||
import ru.gravit.launcher.request.RequestType;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.utils.helper.LogHelper;
|
||||
|
||||
public class ExecCommandRequest extends Request<Boolean> {
|
||||
public LogHelper.Output loutput;
|
||||
public String cmd;
|
||||
|
||||
public ExecCommandRequest(LogHelper.Output output, String cmd) {
|
||||
this.loutput = output;
|
||||
this.cmd = cmd;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.EXECCOMMAND.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Boolean requestDo(HInput input, HOutput output) throws Exception {
|
||||
readError(input);
|
||||
output.writeString(cmd, SerializeLimits.MAX_COMMAND);
|
||||
boolean isContinue = true;
|
||||
while (isContinue) {
|
||||
isContinue = input.readBoolean();
|
||||
if (isContinue) {
|
||||
String log = input.readString(SerializeLimits.MAX_COMMAND);
|
||||
if (loutput != null) loutput.println(log);
|
||||
}
|
||||
}
|
||||
readError(input);
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -96,53 +96,6 @@ public AuthRequest(String login, byte[] password, HWID hwid, String auth_id) {
|
|||
this(null, login, password, hwid, auth_id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.AUTH.getNumber();
|
||||
}
|
||||
|
||||
/*public class EchoRequest implements RequestInterface
|
||||
{
|
||||
String echo;
|
||||
|
||||
public EchoRequest(String echo) {
|
||||
this.echo = echo;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLegacyType() {
|
||||
return "echo";
|
||||
}
|
||||
}*/
|
||||
@Override
|
||||
protected AuthRequestEvent requestDo(HInput input, HOutput output) throws IOException {
|
||||
/*try {
|
||||
LegacyRequestBridge.sendRequest(new EchoRequest("Hello World!"));
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}*/
|
||||
output.writeString(login, SerializeLimits.MAX_LOGIN);
|
||||
output.writeBoolean(Launcher.profile != null);
|
||||
if (Launcher.profile != null)
|
||||
output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT);
|
||||
output.writeString(auth_id, SerializeLimits.MAX_QUEUE_SIZE);
|
||||
output.writeString(hwid.getSerializeString(), 0);
|
||||
//output.writeLong(0);
|
||||
//output.writeLong(0);
|
||||
//output.writeLong(0);
|
||||
output.writeByteArray(encryptedPassword, SecurityHelper.CRYPTO_MAX_LENGTH);
|
||||
output.writeString(customText, SerializeLimits.MAX_CUSTOM_TEXT);
|
||||
output.flush();
|
||||
|
||||
// Read UUID and access token
|
||||
readError(input);
|
||||
PlayerProfile pp = new PlayerProfile(input);
|
||||
String accessToken = input.readASCII(-SecurityHelper.TOKEN_STRING_LENGTH);
|
||||
ClientPermissions permissions = new ClientPermissions(input);
|
||||
String protectToken = input.readString(SerializeLimits.MAX_CUSTOM_TEXT);
|
||||
return new AuthRequestEvent(permissions, pp, accessToken, protectToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "auth";
|
||||
|
|
|
@ -1,93 +0,0 @@
|
|||
package ru.gravit.launcher.request.auth;
|
||||
|
||||
import ru.gravit.launcher.ClientPermissions;
|
||||
import ru.gravit.launcher.LauncherAPI;
|
||||
import ru.gravit.launcher.LauncherConfig;
|
||||
import ru.gravit.launcher.LauncherNetworkAPI;
|
||||
import ru.gravit.launcher.profiles.PlayerProfile;
|
||||
import ru.gravit.launcher.request.Request;
|
||||
import ru.gravit.launcher.request.RequestType;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
import ru.gravit.launcher.serialize.SerializeLimits;
|
||||
import ru.gravit.utils.helper.SecurityHelper;
|
||||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public final class AuthServerRequest extends Request<ClientPermissions> {
|
||||
public static final class Result {
|
||||
@LauncherAPI
|
||||
public final PlayerProfile pp;
|
||||
@LauncherAPI
|
||||
public final String accessToken;
|
||||
|
||||
private Result(PlayerProfile pp, String accessToken) {
|
||||
this.pp = pp;
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
}
|
||||
@LauncherNetworkAPI
|
||||
private final String login;
|
||||
@LauncherNetworkAPI
|
||||
private final byte[] encryptedPassword;
|
||||
@LauncherNetworkAPI
|
||||
private final String auth_id;
|
||||
@LauncherNetworkAPI
|
||||
private final String title;
|
||||
|
||||
@LauncherAPI
|
||||
public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPassword) {
|
||||
super(config);
|
||||
this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty");
|
||||
this.encryptedPassword = encryptedPassword.clone();
|
||||
auth_id = "";
|
||||
title = "";
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPassword, String auth_id) {
|
||||
super(config);
|
||||
this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty");
|
||||
this.encryptedPassword = encryptedPassword.clone();
|
||||
this.auth_id = auth_id;
|
||||
title = "";
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public AuthServerRequest(LauncherConfig config, String login, byte[] encryptedPassword, String auth_id, String title) {
|
||||
super(config);
|
||||
this.login = VerifyHelper.verify(login, VerifyHelper.NOT_EMPTY, "Login can't be empty");
|
||||
this.encryptedPassword = encryptedPassword.clone();
|
||||
this.auth_id = auth_id;
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public AuthServerRequest(String login, byte[] encryptedPassword) {
|
||||
this(null, login, encryptedPassword);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public AuthServerRequest(String login, byte[] encryptedPassword, String auth_id) {
|
||||
this(null, login, encryptedPassword, auth_id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.SERVERAUTH.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ClientPermissions requestDo(HInput input, HOutput output) throws IOException {
|
||||
output.writeString(login, SerializeLimits.MAX_LOGIN);
|
||||
output.writeString(title, SerializeLimits.MAX_CLIENT);
|
||||
output.writeString(auth_id, SerializeLimits.MAX_QUEUE_SIZE);
|
||||
output.writeByteArray(encryptedPassword, SecurityHelper.CRYPTO_MAX_LENGTH);
|
||||
output.flush();
|
||||
|
||||
// Read UUID and access token
|
||||
readError(input);
|
||||
return new ClientPermissions(input);
|
||||
}
|
||||
}
|
|
@ -1,41 +0,0 @@
|
|||
package ru.gravit.launcher.request.auth;
|
||||
|
||||
import ru.gravit.launcher.Launcher;
|
||||
import ru.gravit.launcher.request.Request;
|
||||
import ru.gravit.launcher.request.RequestType;
|
||||
import ru.gravit.launcher.serialize.HInput;
|
||||
import ru.gravit.launcher.serialize.HOutput;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
public class ChangeServerRequest extends Request<ChangeServerRequest.Result> {
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.CHANGESERVER.getNumber();
|
||||
}
|
||||
|
||||
public boolean change(Result result) {
|
||||
if (!result.needChange) return false;
|
||||
Launcher.getConfig().address = InetSocketAddress.createUnresolved(result.address, result.port);
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result requestDo(HInput input, HOutput output) throws Exception {
|
||||
readError(input);
|
||||
Result result = new Result();
|
||||
result.needChange = input.readBoolean();
|
||||
if (result.needChange) {
|
||||
result.address = input.readString(255);
|
||||
result.port = input.readInt();
|
||||
}
|
||||
if (result.needChange) change(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public class Result {
|
||||
public boolean needChange;
|
||||
public String address;
|
||||
public int port;
|
||||
}
|
||||
}
|
|
@ -43,27 +43,6 @@ public CheckServerRequestEvent requestWebSockets() throws Exception
|
|||
return (CheckServerRequestEvent) LegacyRequestBridge.sendRequest(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.CHECK_SERVER.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CheckServerRequestEvent requestDo(HInput input, HOutput output) throws IOException {
|
||||
output.writeString(username, SerializeLimits.MAX_LOGIN);
|
||||
output.writeASCII(serverID, SerializeLimits.MAX_SERVERID); // 1 char for minus sign
|
||||
if (Launcher.profile == null) {
|
||||
LogHelper.error("Profile is null. Title is not net.");
|
||||
output.writeString("", SerializeLimits.MAX_CLIENT);
|
||||
} else
|
||||
output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT);
|
||||
output.flush();
|
||||
|
||||
// Read response
|
||||
readError(input);
|
||||
return input.readBoolean() ? new CheckServerRequestEvent(new PlayerProfile(input)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "checkServer";
|
||||
|
|
|
@ -43,24 +43,6 @@ public JoinServerRequestEvent requestWebSockets() throws IOException, Interrupte
|
|||
public JoinServerRequest(String username, String accessToken, String serverID) {
|
||||
this(null, username, accessToken, serverID);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.JOIN_SERVER.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JoinServerRequestEvent requestDo(HInput input, HOutput output) throws IOException {
|
||||
output.writeString(username, SerializeLimits.MAX_LOGIN);
|
||||
output.writeASCII(accessToken, -SecurityHelper.TOKEN_STRING_LENGTH);
|
||||
output.writeASCII(serverID, SerializeLimits.MAX_SERVERID); // 1 char for minus sign
|
||||
output.flush();
|
||||
|
||||
// Read response
|
||||
readError(input);
|
||||
return new JoinServerRequestEvent(input.readBoolean());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "joinServer";
|
||||
|
|
|
@ -23,16 +23,6 @@ public RestoreSessionRequestEvent requestWebSockets() throws IOException, Interr
|
|||
return (RestoreSessionRequestEvent) LegacyRequestBridge.sendRequest(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RestoreSessionRequestEvent requestDo(HInput input, HOutput output) throws Exception {
|
||||
return new RestoreSessionRequestEvent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "restoreSession";
|
||||
|
|
|
@ -28,18 +28,6 @@ public SetProfileRequestEvent requestWebSockets() throws Exception {
|
|||
return (SetProfileRequestEvent) LegacyRequestBridge.sendRequest(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.SETPROFILE.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SetProfileRequestEvent requestDo(HInput input, HOutput output) throws Exception {
|
||||
output.writeString(profile.getTitle(), SerializeLimits.MAX_CLIENT);
|
||||
readError(input);
|
||||
return new SetProfileRequestEvent(profile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "setProfile";
|
||||
|
|
|
@ -93,30 +93,6 @@ public LauncherRequest(LauncherConfig config) {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.LAUNCHER.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected LauncherRequestEvent requestDo(HInput input, HOutput output) throws Exception {
|
||||
output.writeBoolean(EXE_BINARY);
|
||||
output.writeByteArray(digest, 0);
|
||||
output.flush();
|
||||
readError(input);
|
||||
|
||||
// Verify launcher sign
|
||||
boolean shouldUpdate = input.readBoolean();
|
||||
if (shouldUpdate) {
|
||||
byte[] binary = input.readByteArray(0);
|
||||
LauncherRequestEvent result = new LauncherRequestEvent(binary, digest);
|
||||
update(Launcher.getConfig(), result);
|
||||
}
|
||||
|
||||
// Return request result
|
||||
return new LauncherRequestEvent(null, digest);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "launcher";
|
||||
|
|
|
@ -84,41 +84,4 @@ public LegacyLauncherRequest() {
|
|||
public LegacyLauncherRequest(LauncherConfig config) {
|
||||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.LEGACYLAUNCHER.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Result requestDo(HInput input, HOutput output) throws Exception {
|
||||
output.writeBoolean(EXE_BINARY);
|
||||
output.flush();
|
||||
readError(input);
|
||||
|
||||
// Verify launcher sign
|
||||
RSAPublicKey publicKey = config.publicKey;
|
||||
byte[] sign = input.readByteArray(-SecurityHelper.RSA_KEY_LENGTH);
|
||||
boolean shouldUpdate = !SecurityHelper.isValidSign(BINARY_PATH, sign, publicKey);
|
||||
|
||||
// Update launcher if need
|
||||
output.writeBoolean(shouldUpdate);
|
||||
output.flush();
|
||||
if (shouldUpdate) {
|
||||
byte[] binary = input.readByteArray(0);
|
||||
SecurityHelper.verifySign(binary, sign, config.publicKey);
|
||||
return new Result(binary, sign, Collections.emptyList());
|
||||
}
|
||||
|
||||
// Read clients profiles list
|
||||
int count = input.readLength(0);
|
||||
List<ClientProfile> profiles = new ArrayList<>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
String prof = input.readString(0);
|
||||
profiles.add(Launcher.gson.fromJson(prof, ClientProfile.class));
|
||||
}
|
||||
|
||||
// Return request result
|
||||
return new Result(null, sign, profiles);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,32 +27,11 @@ public ProfilesRequest(LauncherConfig config) {
|
|||
super(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.PROFILES.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProfilesRequestEvent requestWebSockets() throws Exception {
|
||||
return (ProfilesRequestEvent) LegacyRequestBridge.sendRequest(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProfilesRequestEvent requestDo(HInput input, HOutput output) throws Exception {
|
||||
output.writeBoolean(true);
|
||||
output.flush();
|
||||
readError(input);
|
||||
|
||||
int count = input.readLength(0);
|
||||
List<ClientProfile> profiles = new ArrayList<>(count);
|
||||
for (int i = 0; i < count; i++) {
|
||||
String prof = input.readString(0);
|
||||
profiles.add(Launcher.gson.fromJson(prof, ClientProfile.class));
|
||||
}
|
||||
// Return request result
|
||||
return new ProfilesRequestEvent(profiles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "profiles";
|
||||
|
|
|
@ -30,24 +30,6 @@ public UpdateListRequestEvent requestWebSockets() throws Exception {
|
|||
return (UpdateListRequestEvent) LegacyRequestBridge.sendRequest(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.UPDATE_LIST.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UpdateListRequestEvent requestDo(HInput input, HOutput output) throws IOException {
|
||||
int count = input.readLength(0);
|
||||
|
||||
// Read all update dirs names
|
||||
HashSet<String> result = new HashSet<>(count);
|
||||
for (int i = 0; i < count; i++)
|
||||
result.add(IOHelper.verifyFileName(input.readString(255)));
|
||||
|
||||
// We're done. Make it unmodifiable and return
|
||||
return new UpdateListRequestEvent(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "updateList";
|
||||
|
|
|
@ -284,48 +284,6 @@ private void deleteExtraDir(Path subDir, HashedDir subHDir, boolean flag) throws
|
|||
}
|
||||
}
|
||||
|
||||
private void downloadFile(Path file, HashedFile hFile, InputStream input) throws IOException {
|
||||
String filePath = IOHelper.toString(dir.relativize(file));
|
||||
updateState(filePath, 0L, hFile.size);
|
||||
|
||||
// Start file update
|
||||
MessageDigest digest = this.digest ? SecurityHelper.newDigest(DigestAlgorithm.MD5) : null;
|
||||
try (OutputStream fileOutput = IOHelper.newOutput(file)) {
|
||||
long downloaded = 0L;
|
||||
|
||||
// Download with digest update
|
||||
byte[] bytes = IOHelper.newBuffer();
|
||||
while (downloaded < hFile.size) {
|
||||
int remaining = (int) Math.min(hFile.size - downloaded, bytes.length);
|
||||
int length = input.read(bytes, 0, remaining);
|
||||
if (length < 0)
|
||||
throw new EOFException(String.format("%d bytes remaining", hFile.size - downloaded));
|
||||
|
||||
// Update file
|
||||
fileOutput.write(bytes, 0, length);
|
||||
if (digest != null)
|
||||
digest.update(bytes, 0, length);
|
||||
|
||||
// Update state
|
||||
downloaded += length;
|
||||
totalDownloaded += length;
|
||||
updateState(filePath, downloaded, hFile.size);
|
||||
}
|
||||
}
|
||||
|
||||
// Verify digest
|
||||
if (digest != null) {
|
||||
byte[] digestBytes = digest.digest();
|
||||
if (!hFile.isSameDigest(digestBytes))
|
||||
throw new SecurityException(String.format("File digest mismatch: '%s'", filePath));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.UPDATE.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
public UpdateRequestEvent request() throws Exception {
|
||||
Files.createDirectories(dir);
|
||||
|
@ -335,76 +293,6 @@ public UpdateRequestEvent request() throws Exception {
|
|||
return super.request();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected UpdateRequestEvent requestDo(HInput input, HOutput output) throws IOException, SignatureException {
|
||||
// Write update dir name
|
||||
output.writeString(dirName, 255);
|
||||
output.flush();
|
||||
readError(input);
|
||||
|
||||
// Get diff between local and remote dir
|
||||
SignedObjectHolder<HashedDir> remoteHDirHolder = new SignedObjectHolder<>(input, config.publicKey, HashedDir::new);
|
||||
HashedDir hackHackedDir = remoteHDirHolder.object;
|
||||
Launcher.profile.pushOptionalFile(hackHackedDir, !Launcher.profile.isUpdateFastCheck());
|
||||
HashedDir.Diff diff = hackHackedDir.diff(localDir, matcher);
|
||||
totalSize = diff.mismatch.size();
|
||||
boolean compress = input.readBoolean();
|
||||
|
||||
// Build actions queue
|
||||
Queue<UpdateAction> queue = new LinkedList<>();
|
||||
fillActionsQueue(queue, diff.mismatch);
|
||||
queue.add(UpdateAction.FINISH);
|
||||
|
||||
// noinspection IOResourceOpenedButNotSafelyClosed
|
||||
InputStream fileInput = compress ? new InflaterInputStream(input.stream, IOHelper.newInflater(), IOHelper.BUFFER_SIZE) : input.stream;
|
||||
|
||||
// Download missing first
|
||||
// (otherwise it will cause mustdie indexing bug)
|
||||
startTime = Instant.now();
|
||||
Path currentDir = dir;
|
||||
UpdateAction[] actionsSlice = new UpdateAction[SerializeLimits.MAX_QUEUE_SIZE];
|
||||
while (!queue.isEmpty()) {
|
||||
int length = Math.min(queue.size(), SerializeLimits.MAX_QUEUE_SIZE);
|
||||
|
||||
// Write actions slice
|
||||
output.writeLength(length, SerializeLimits.MAX_QUEUE_SIZE);
|
||||
for (int i = 0; i < length; i++) {
|
||||
UpdateAction action = queue.remove();
|
||||
actionsSlice[i] = action;
|
||||
action.write(output);
|
||||
}
|
||||
output.flush();
|
||||
|
||||
// Perform actions
|
||||
for (int i = 0; i < length; i++) {
|
||||
UpdateAction action = actionsSlice[i];
|
||||
switch (action.type) {
|
||||
case CD:
|
||||
currentDir = currentDir.resolve(action.name);
|
||||
Files.createDirectories(currentDir);
|
||||
break;
|
||||
case GET:
|
||||
Path targetFile = currentDir.resolve(action.name);
|
||||
if (fileInput.read() != 0xFF)
|
||||
throw new IOException("Serverside cached size mismath for file " + action.name);
|
||||
downloadFile(targetFile, (HashedFile) action.entry, fileInput);
|
||||
break;
|
||||
case CD_BACK:
|
||||
currentDir = currentDir.getParent();
|
||||
break;
|
||||
case FINISH:
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError(String.format("Unsupported action type: '%s'", action.type.name()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Write update completed packet
|
||||
deleteExtraDir(dir, diff.extra, diff.extra.flag);
|
||||
return new UpdateRequestEvent(remoteHDirHolder.object);
|
||||
}
|
||||
|
||||
@LauncherAPI
|
||||
public void setStateCallback(Callback callback) {
|
||||
stateCallback = callback;
|
||||
|
|
|
@ -50,29 +50,6 @@ public BatchProfileByUsernameRequestEvent requestWebSockets() throws IOException
|
|||
return (BatchProfileByUsernameRequestEvent) LegacyRequestBridge.sendRequest(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.BATCH_PROFILE_BY_USERNAME.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BatchProfileByUsernameRequestEvent requestDo(HInput input, HOutput output) throws IOException {
|
||||
output.writeLength(list.length, SerializeLimits.MAX_BATCH_SIZE);
|
||||
for (Entry username : list) {
|
||||
output.writeString(username.username, SerializeLimits.MAX_LOGIN);
|
||||
output.writeString(username.client, SerializeLimits.MAX_CLIENT);
|
||||
}
|
||||
output.flush();
|
||||
|
||||
// Read profiles response
|
||||
PlayerProfile[] profiles = new PlayerProfile[list.length];
|
||||
for (int i = 0; i < profiles.length; i++)
|
||||
profiles[i] = input.readBoolean() ? new PlayerProfile(input) : null;
|
||||
|
||||
// Return result
|
||||
return new BatchProfileByUsernameRequestEvent(profiles);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "batchProfileByUsername";
|
||||
|
|
|
@ -38,21 +38,6 @@ public ProfileByUUIDRequestEvent requestWebSockets() throws IOException, Interru
|
|||
return (ProfileByUUIDRequestEvent) LegacyRequestBridge.sendRequest(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.PROFILE_BY_UUID.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProfileByUUIDRequestEvent requestDo(HInput input, HOutput output) throws IOException {
|
||||
output.writeUUID(uuid);
|
||||
output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT);
|
||||
output.flush();
|
||||
|
||||
// Return profile
|
||||
return input.readBoolean() ? new ProfileByUUIDRequestEvent(new PlayerProfile(input)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "profileByUUID";
|
||||
|
|
|
@ -37,20 +37,6 @@ public ProfileByUsernameRequestEvent requestWebSockets() throws IOException, Int
|
|||
return (ProfileByUsernameRequestEvent) LegacyRequestBridge.sendRequest(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getLegacyType() {
|
||||
return RequestType.PROFILE_BY_USERNAME.getNumber();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProfileByUsernameRequestEvent requestDo(HInput input, HOutput output) throws IOException {
|
||||
output.writeString(username, SerializeLimits.MAX_LOGIN);
|
||||
output.writeString(Launcher.profile.getTitle(), SerializeLimits.MAX_CLIENT);
|
||||
output.flush();
|
||||
// Return profile
|
||||
return input.readBoolean() ? new ProfileByUsernameRequestEvent(new PlayerProfile(input)) : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "profileByUsername";
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
import ru.gravit.launcher.events.request.ProfilesRequestEvent;
|
||||
import ru.gravit.launcher.profiles.ClientProfile;
|
||||
import ru.gravit.launcher.request.auth.AuthRequest;
|
||||
import ru.gravit.launcher.request.auth.AuthServerRequest;
|
||||
import ru.gravit.launcher.request.update.ProfilesRequest;
|
||||
import ru.gravit.launcher.request.websockets.LegacyRequestBridge;
|
||||
import ru.gravit.launcher.server.setup.ServerWrapperSetup;
|
||||
|
@ -53,13 +52,8 @@ public ServerWrapper(Type type, Path configPath) {
|
|||
public boolean auth() {
|
||||
try {
|
||||
LauncherConfig cfg = Launcher.getConfig();
|
||||
if(!config.websocket.enabled)
|
||||
permissions = new AuthServerRequest(cfg, config.login, SecurityHelper.newRSAEncryptCipher(cfg.publicKey).doFinal(IOHelper.encode(config.password)), config.auth_id, config.title).request();
|
||||
else
|
||||
{
|
||||
AuthRequest request = new AuthRequest(config.login, SecurityHelper.newRSAEncryptCipher(cfg.publicKey).doFinal(IOHelper.encode(config.password)), config.auth_id, AuthRequest.ConnectTypes.SERVER);
|
||||
permissions = request.request().permissions;
|
||||
}
|
||||
AuthRequest request = new AuthRequest(config.login, SecurityHelper.newRSAEncryptCipher(cfg.publicKey).doFinal(IOHelper.encode(config.password)), config.auth_id, AuthRequest.ConnectTypes.SERVER);
|
||||
permissions = request.request().permissions;
|
||||
ProfilesRequestEvent result = new ProfilesRequest(cfg).request();
|
||||
for (ClientProfile p : result.profiles) {
|
||||
LogHelper.debug("Get profile: %s", p.getTitle());
|
||||
|
@ -184,7 +178,7 @@ public void run(String... args) throws Throwable {
|
|||
auth();
|
||||
};
|
||||
}
|
||||
LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s port %d. Title: %s", config.projectname, config.address, config.port, config.title);
|
||||
LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s port %d. Title: %s", config.projectname, config.websocket.address, config.title);
|
||||
LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name);
|
||||
LogHelper.info("Start Minecraft Server");
|
||||
LogHelper.debug("Invoke main method %s", mainClass.getName());
|
||||
|
@ -205,7 +199,7 @@ public void updateLauncherConfig() {
|
|||
|
||||
LauncherConfig cfg = null;
|
||||
try {
|
||||
cfg = new LauncherConfig(config.address, config.port, SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile)), new HashMap<>(), config.projectname);
|
||||
cfg = new LauncherConfig(config.websocket.address, SecurityHelper.toPublicRSAKey(IOHelper.read(publicKeyFile)), new HashMap<>(), config.projectname);
|
||||
if(config.websocket != null && config.websocket.enabled)
|
||||
{
|
||||
cfg.isNettyEnabled = true;
|
||||
|
@ -235,8 +229,6 @@ public Config getDefaultConfig() {
|
|||
Config newConfig = new Config();
|
||||
newConfig.title = "Your profile title";
|
||||
newConfig.projectname = "MineCraft";
|
||||
newConfig.address = "localhost";
|
||||
newConfig.port = 7240;
|
||||
newConfig.login = "login";
|
||||
newConfig.password = "password";
|
||||
newConfig.mainclass = "";
|
||||
|
@ -259,9 +251,7 @@ public void setConfig(Config config) {
|
|||
public static final class Config {
|
||||
public String title;
|
||||
public String projectname;
|
||||
public String address;
|
||||
public WebSocketConf websocket;
|
||||
public int port;
|
||||
public int reconnectCount;
|
||||
public int reconnectSleep;
|
||||
public boolean customClassPath;
|
||||
|
|
|
@ -40,13 +40,10 @@ public void run() throws IOException {
|
|||
return;
|
||||
}
|
||||
LogHelper.info("Found MainClass %s", mainClassName);
|
||||
System.out.println("Print launchserver host:");
|
||||
System.out.println("Print launchserver websocket host:");
|
||||
String address = commands.commandHandler.readLine();
|
||||
System.out.println("Print launchserver port:");
|
||||
int port = Integer.valueOf(commands.commandHandler.readLine());
|
||||
wrapper.config.mainclass = mainClassName;
|
||||
wrapper.config.address = address;
|
||||
wrapper.config.port = port;
|
||||
wrapper.config.websocket.address = address;
|
||||
if (!Files.exists(ServerWrapper.publicKeyFile)) {
|
||||
LogHelper.error("public.key not found");
|
||||
for (int i = 0; i < 10; ++i) {
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
import ru.gravit.utils.helper.VerifyHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.security.interfaces.RSAPublicKey;
|
||||
import java.security.spec.InvalidKeySpecException;
|
||||
import java.util.*;
|
||||
|
@ -21,8 +20,6 @@ public static AutogenConfig getAutogenConfig() {
|
|||
}
|
||||
|
||||
// Instance
|
||||
@LauncherAPI
|
||||
public InetSocketAddress address;
|
||||
public String nettyAddress;
|
||||
public int nettyPort;
|
||||
@LauncherAPI
|
||||
|
@ -46,7 +43,6 @@ public static AutogenConfig getAutogenConfig() {
|
|||
|
||||
@LauncherAPI
|
||||
public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException {
|
||||
address = InetSocketAddress.createUnresolved(config.address, config.port);
|
||||
publicKey = SecurityHelper.toPublicRSAKey(input.readByteArray(SecurityHelper.CRYPTO_MAX_LENGTH));
|
||||
projectname = config.projectname;
|
||||
clientPort = config.clientPort;
|
||||
|
@ -80,8 +76,8 @@ public LauncherConfig(HInput input) throws IOException, InvalidKeySpecException
|
|||
}
|
||||
|
||||
@LauncherAPI
|
||||
public LauncherConfig(String address, int port, RSAPublicKey publicKey, Map<String, byte[]> runtime, String projectname) {
|
||||
this.address = InetSocketAddress.createUnresolved(address, port);
|
||||
public LauncherConfig(String address, RSAPublicKey publicKey, Map<String, byte[]> runtime, String projectname) {
|
||||
this.nettyAddress = address;
|
||||
this.publicKey = Objects.requireNonNull(publicKey, "publicKey");
|
||||
this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime));
|
||||
this.projectname = projectname;
|
||||
|
@ -96,8 +92,8 @@ public LauncherConfig(String address, int port, RSAPublicKey publicKey, Map<Stri
|
|||
}
|
||||
|
||||
@LauncherAPI
|
||||
public LauncherConfig(String address, int port, RSAPublicKey publicKey, Map<String, byte[]> runtime) {
|
||||
this.address = InetSocketAddress.createUnresolved(address, port);
|
||||
public LauncherConfig(String address, RSAPublicKey publicKey, Map<String, byte[]> runtime) {
|
||||
this.nettyAddress = address;
|
||||
this.publicKey = Objects.requireNonNull(publicKey, "publicKey");
|
||||
this.runtime = Collections.unmodifiableMap(new HashMap<>(runtime));
|
||||
this.projectname = "Minecraft";
|
||||
|
|
Loading…
Reference in a new issue