mirror of
https://github.com/GravitLauncher/Launcher
synced 2025-03-28 20:18:21 +03:00
[ANY] New Sessions system completed
This commit is contained in:
parent
acf2d2d9cd
commit
c596c30ff6
10 changed files with 171 additions and 158 deletions
|
@ -10,6 +10,7 @@
|
||||||
import pro.gravit.launcher.modules.events.ClosePhase;
|
import pro.gravit.launcher.modules.events.ClosePhase;
|
||||||
import pro.gravit.launcher.profiles.ClientProfile;
|
import pro.gravit.launcher.profiles.ClientProfile;
|
||||||
import pro.gravit.launchserver.auth.AuthProviderPair;
|
import pro.gravit.launchserver.auth.AuthProviderPair;
|
||||||
|
import pro.gravit.launchserver.auth.session.MemorySessionStorage;
|
||||||
import pro.gravit.launchserver.binary.*;
|
import pro.gravit.launchserver.binary.*;
|
||||||
import pro.gravit.launchserver.config.LaunchServerConfig;
|
import pro.gravit.launchserver.config.LaunchServerConfig;
|
||||||
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
|
import pro.gravit.launchserver.config.LaunchServerRuntimeConfig;
|
||||||
|
@ -128,6 +129,7 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La
|
||||||
|
|
||||||
runtime.verify();
|
runtime.verify();
|
||||||
config.verify();
|
config.verify();
|
||||||
|
if(config.sessions == null) config.sessions = new MemorySessionStorage();
|
||||||
if (config.components != null) {
|
if (config.components != null) {
|
||||||
LogHelper.debug("PreInit components");
|
LogHelper.debug("PreInit components");
|
||||||
config.components.forEach((k, v) -> {
|
config.components.forEach((k, v) -> {
|
||||||
|
@ -147,7 +149,8 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La
|
||||||
pingServerManager = new PingServerManager(this);
|
pingServerManager = new PingServerManager(this);
|
||||||
//Generate or set new Certificate API
|
//Generate or set new Certificate API
|
||||||
certificateManager.orgName = config.projectName;
|
certificateManager.orgName = config.projectName;
|
||||||
if (config.certificate != null && config.certificate.enabled) {
|
/*
|
||||||
|
if (false) {
|
||||||
if (IOHelper.isFile(caCertFile) && IOHelper.isFile(caKeyFile)) {
|
if (IOHelper.isFile(caCertFile) && IOHelper.isFile(caKeyFile)) {
|
||||||
certificateManager.ca = certificateManager.readCertificate(caCertFile);
|
certificateManager.ca = certificateManager.readCertificate(caCertFile);
|
||||||
certificateManager.caKey = certificateManager.readPrivateKey(caKeyFile);
|
certificateManager.caKey = certificateManager.readPrivateKey(caKeyFile);
|
||||||
|
@ -175,6 +178,7 @@ public LaunchServer(LaunchServerDirectories directories, LaunchServerEnv env, La
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
config.init(ReloadType.FULL);
|
config.init(ReloadType.FULL);
|
||||||
registerObject("launchServer", this);
|
registerObject("launchServer", this);
|
||||||
GarbageManager.registerNeedGC(sessionManager);
|
GarbageManager.registerNeedGC(sessionManager);
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
package pro.gravit.launchserver.auth.session;
|
||||||
|
|
||||||
|
import pro.gravit.launcher.NeedGarbageCollection;
|
||||||
|
import pro.gravit.launchserver.manangers.SessionManager;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class MemorySessionStorage extends SessionStorage implements NeedGarbageCollection {
|
||||||
|
|
||||||
|
private final Map<UUID, Entry> clientSet = new ConcurrentHashMap<>(128);
|
||||||
|
private final Map<UUID, Set<Entry>> uuidIndex = new ConcurrentHashMap<>(32);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getSessionData(UUID session) {
|
||||||
|
|
||||||
|
Entry e = clientSet.get(session);
|
||||||
|
if(e == null) return null;
|
||||||
|
return e.data;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Stream<UUID> getSessionsFromUserUUID(UUID userUUID) {
|
||||||
|
Set<Entry> set = uuidIndex.get(userUUID);
|
||||||
|
if(set != null) return set.stream().map((e) -> e.sessionUuid);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean writeSession(UUID userUUID, UUID sessionUUID, byte[] data) {
|
||||||
|
deleteSession(sessionUUID);
|
||||||
|
Entry e = new Entry(data, sessionUUID);
|
||||||
|
clientSet.put(sessionUUID, e);
|
||||||
|
if(userUUID != null) {
|
||||||
|
Set<Entry> uuidSet = uuidIndex.computeIfAbsent(userUUID, k -> ConcurrentHashMap.newKeySet());
|
||||||
|
uuidSet.add(e);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteSession(UUID sessionUUID) {
|
||||||
|
Entry e =clientSet.remove(sessionUUID);
|
||||||
|
if(e != null) {
|
||||||
|
Set<Entry> set = uuidIndex.get(sessionUUID);
|
||||||
|
if(set != null) {
|
||||||
|
removeUuidFromIndexSet(set, e, sessionUUID);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean deleteSessionsByUserUUID(UUID userUUID) {
|
||||||
|
Set<Entry> set = uuidIndex.get(userUUID);
|
||||||
|
if(set != null) {
|
||||||
|
for(Entry e : set) {
|
||||||
|
clientSet.remove(e.sessionUuid);
|
||||||
|
}
|
||||||
|
set.clear();
|
||||||
|
uuidIndex.remove(userUUID);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void clear() {
|
||||||
|
clientSet.clear();
|
||||||
|
uuidIndex.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void removeUuidFromIndexSet(Set<Entry> set, Entry e, UUID session) {
|
||||||
|
set.remove(e);
|
||||||
|
if(set.isEmpty()) {
|
||||||
|
uuidIndex.remove(session);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void garbageCollection() {
|
||||||
|
long time = System.currentTimeMillis();
|
||||||
|
long session_timeout = server.config.netty.performance.sessionLifetimeMs;
|
||||||
|
Set<UUID> to_delete = new HashSet<>(32);
|
||||||
|
clientSet.forEach((uuid, entry) -> {
|
||||||
|
long timestamp = entry.timestamp;
|
||||||
|
if(timestamp + session_timeout < time)
|
||||||
|
to_delete.add(uuid);
|
||||||
|
});
|
||||||
|
for(UUID session : to_delete) {
|
||||||
|
deleteSession(session);
|
||||||
|
}
|
||||||
|
to_delete.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Entry {
|
||||||
|
public byte[] data;
|
||||||
|
public UUID sessionUuid;
|
||||||
|
public long timestamp;
|
||||||
|
|
||||||
|
public Entry(byte[] data, UUID sessionUuid) {
|
||||||
|
this.data = data;
|
||||||
|
this.sessionUuid = sessionUuid;
|
||||||
|
this.timestamp = System.currentTimeMillis();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package pro.gravit.launchserver.auth.session;
|
||||||
|
|
||||||
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
|
import pro.gravit.utils.ProviderMap;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public abstract class SessionStorage {
|
||||||
|
protected transient LaunchServer server;
|
||||||
|
public static ProviderMap<SessionStorage> providers = new ProviderMap<>();
|
||||||
|
public abstract byte[] getSessionData(UUID session);
|
||||||
|
public abstract Stream<UUID> getSessionsFromUserUUID(UUID userUUID);
|
||||||
|
public abstract boolean writeSession(UUID userUUID, UUID sessionUUID, byte[] data);
|
||||||
|
public abstract boolean deleteSession(UUID sessionUUID);
|
||||||
|
public boolean deleteSessionsByUserUUID(UUID userUUID) {
|
||||||
|
getSessionsFromUserUUID(userUUID).forEach(this::deleteSession);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
public abstract void clear();
|
||||||
|
public void init(LaunchServer server)
|
||||||
|
{
|
||||||
|
this.server = server;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,67 +0,0 @@
|
||||||
package pro.gravit.launchserver.command.dump;
|
|
||||||
|
|
||||||
import com.google.gson.reflect.TypeToken;
|
|
||||||
import pro.gravit.launcher.Launcher;
|
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
|
||||||
import pro.gravit.launchserver.command.Command;
|
|
||||||
import pro.gravit.launchserver.socket.Client;
|
|
||||||
import pro.gravit.utils.command.SubCommand;
|
|
||||||
import pro.gravit.utils.helper.IOHelper;
|
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
|
||||||
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.io.Writer;
|
|
||||||
import java.lang.reflect.Type;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
public class DumpSessionsCommand extends Command {
|
|
||||||
public DumpSessionsCommand(LaunchServer server) {
|
|
||||||
super(server);
|
|
||||||
childCommands.put("load", new SubCommand() {
|
|
||||||
@Override
|
|
||||||
public void invoke(String... args) throws Exception {
|
|
||||||
verifyArgs(args, 1);
|
|
||||||
LogHelper.info("Sessions read from %s", args[0]);
|
|
||||||
int size;
|
|
||||||
try (Reader reader = IOHelper.newReader(Paths.get(args[0]))) {
|
|
||||||
Type setType = new TypeToken<HashSet<Client>>() {
|
|
||||||
}.getType();
|
|
||||||
Set<Client> clientSet = Launcher.gsonManager.configGson.fromJson(reader, setType);
|
|
||||||
size = clientSet.size();
|
|
||||||
server.sessionManager.loadSessions(clientSet);
|
|
||||||
}
|
|
||||||
LogHelper.subInfo("Readed %d sessions", size);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
childCommands.put("unload", new SubCommand() {
|
|
||||||
@Override
|
|
||||||
public void invoke(String... args) throws Exception {
|
|
||||||
verifyArgs(args, 1);
|
|
||||||
LogHelper.info("Sessions write to %s", args[0]);
|
|
||||||
Collection<Client> clientSet = server.sessionManager.getSessions();
|
|
||||||
try (Writer writer = IOHelper.newWriter(Paths.get(args[0]))) {
|
|
||||||
Launcher.gsonManager.configGson.toJson(clientSet, writer);
|
|
||||||
}
|
|
||||||
LogHelper.subInfo("Write %d sessions", clientSet.size());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getArgsDescription() {
|
|
||||||
return "[load/unload] [filename]";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getUsageDescription() {
|
|
||||||
return "Load or unload sessions";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void invoke(String... args) throws Exception {
|
|
||||||
invokeSubcommands(args);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,7 +5,6 @@
|
||||||
import pro.gravit.launchserver.command.auth.UUIDToUsernameCommand;
|
import pro.gravit.launchserver.command.auth.UUIDToUsernameCommand;
|
||||||
import pro.gravit.launchserver.command.auth.UsernameToUUIDCommand;
|
import pro.gravit.launchserver.command.auth.UsernameToUUIDCommand;
|
||||||
import pro.gravit.launchserver.command.basic.*;
|
import pro.gravit.launchserver.command.basic.*;
|
||||||
import pro.gravit.launchserver.command.dump.DumpSessionsCommand;
|
|
||||||
import pro.gravit.launchserver.command.hash.*;
|
import pro.gravit.launchserver.command.hash.*;
|
||||||
import pro.gravit.launchserver.command.install.CheckInstallCommand;
|
import pro.gravit.launchserver.command.install.CheckInstallCommand;
|
||||||
import pro.gravit.launchserver.command.install.MultiCommand;
|
import pro.gravit.launchserver.command.install.MultiCommand;
|
||||||
|
@ -61,12 +60,6 @@ public static void registerCommands(pro.gravit.utils.command.CommandHandler hand
|
||||||
Category authCategory = new Category(auth, "auth", "User Management");
|
Category authCategory = new Category(auth, "auth", "User Management");
|
||||||
handler.registerCategory(authCategory);
|
handler.registerCategory(authCategory);
|
||||||
|
|
||||||
//Register dump commands
|
|
||||||
BaseCommandCategory dump = new BaseCommandCategory();
|
|
||||||
dump.registerCommand("dumpSessions", new DumpSessionsCommand(server));
|
|
||||||
Category dumpCategory = new Category(dump, "dump", "Dump runtime data");
|
|
||||||
handler.registerCategory(dumpCategory);
|
|
||||||
|
|
||||||
//Register service commands
|
//Register service commands
|
||||||
BaseCommandCategory service = new BaseCommandCategory();
|
BaseCommandCategory service = new BaseCommandCategory();
|
||||||
service.registerCommand("config", new ConfigCommand(server));
|
service.registerCommand("config", new ConfigCommand(server));
|
||||||
|
|
|
@ -38,7 +38,7 @@ public void invoke(String... args) {
|
||||||
for (CommandHandler.Category category : server.commandHandler.getCategories()) {
|
for (CommandHandler.Category category : server.commandHandler.getCategories()) {
|
||||||
commands += category.category.commandsMap().size();
|
commands += category.category.commandsMap().size();
|
||||||
}
|
}
|
||||||
LogHelper.info("Sessions: %d | Commands: %d(%d categories)", server.sessionManager.getSessions().size(), commands, server.commandHandler.getCategories().size() + 1);
|
LogHelper.info("Commands: %d(%d categories)", commands, server.commandHandler.getCategories().size() + 1);
|
||||||
for (AuthProviderPair pair : server.config.auth.values()) {
|
for (AuthProviderPair pair : server.config.auth.values()) {
|
||||||
if (pair.handler instanceof CachedAuthHandler) {
|
if (pair.handler instanceof CachedAuthHandler) {
|
||||||
LogHelper.info("AuthHandler %s: EntryCache: %d | usernameCache: %d", pair.name, ((CachedAuthHandler) pair.handler).getEntryCache().size(), ((CachedAuthHandler) pair.handler).getUsernamesCache().size());
|
LogHelper.info("AuthHandler %s: EntryCache: %d | usernameCache: %d", pair.name, ((CachedAuthHandler) pair.handler).getEntryCache().size(), ((CachedAuthHandler) pair.handler).getUsernamesCache().size());
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
||||||
import pro.gravit.launchserver.auth.protect.StdProtectHandler;
|
import pro.gravit.launchserver.auth.protect.StdProtectHandler;
|
||||||
import pro.gravit.launchserver.auth.provider.RejectAuthProvider;
|
import pro.gravit.launchserver.auth.provider.RejectAuthProvider;
|
||||||
|
import pro.gravit.launchserver.auth.session.MemorySessionStorage;
|
||||||
|
import pro.gravit.launchserver.auth.session.SessionStorage;
|
||||||
import pro.gravit.launchserver.auth.texture.RequestTextureProvider;
|
import pro.gravit.launchserver.auth.texture.RequestTextureProvider;
|
||||||
import pro.gravit.launchserver.binary.tasks.exe.Launch4JTask;
|
import pro.gravit.launchserver.binary.tasks.exe.Launch4JTask;
|
||||||
import pro.gravit.launchserver.components.AuthLimiterComponent;
|
import pro.gravit.launchserver.components.AuthLimiterComponent;
|
||||||
|
@ -33,6 +35,7 @@ public final class LaunchServerConfig {
|
||||||
public LauncherConfig.LauncherEnvironment env;
|
public LauncherConfig.LauncherEnvironment env;
|
||||||
public Map<String, AuthProviderPair> auth;
|
public Map<String, AuthProviderPair> auth;
|
||||||
public DaoProvider dao;
|
public DaoProvider dao;
|
||||||
|
public SessionStorage sessions;
|
||||||
|
|
||||||
// Handlers & Providers
|
// Handlers & Providers
|
||||||
public ProtectHandler protectHandler;
|
public ProtectHandler protectHandler;
|
||||||
|
@ -40,7 +43,6 @@ public final class LaunchServerConfig {
|
||||||
public ExeConf launch4j;
|
public ExeConf launch4j;
|
||||||
public NettyConfig netty;
|
public NettyConfig netty;
|
||||||
public LauncherConf launcher;
|
public LauncherConf launcher;
|
||||||
public CertificateConf certificate;
|
|
||||||
public JarSignerConf sign;
|
public JarSignerConf sign;
|
||||||
public String startScript;
|
public String startScript;
|
||||||
private transient LaunchServer server = null;
|
private transient LaunchServer server = null;
|
||||||
|
@ -71,6 +73,7 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
|
||||||
a.displayName = "Default";
|
a.displayName = "Default";
|
||||||
newConfig.auth.put("std", a);
|
newConfig.auth.put("std", a);
|
||||||
newConfig.protectHandler = new StdProtectHandler();
|
newConfig.protectHandler = new StdProtectHandler();
|
||||||
|
newConfig.sessions = new MemorySessionStorage();
|
||||||
newConfig.binaryName = "Launcher";
|
newConfig.binaryName = "Launcher";
|
||||||
|
|
||||||
newConfig.netty = new NettyConfig();
|
newConfig.netty = new NettyConfig();
|
||||||
|
@ -97,8 +100,6 @@ public static LaunchServerConfig getDefault(LaunchServer.LaunchServerEnv env) {
|
||||||
newConfig.launcher.stripLineNumbers = true;
|
newConfig.launcher.stripLineNumbers = true;
|
||||||
newConfig.launcher.proguardGenMappings = true;
|
newConfig.launcher.proguardGenMappings = true;
|
||||||
|
|
||||||
newConfig.certificate = new LaunchServerConfig.CertificateConf();
|
|
||||||
newConfig.certificate.enabled = false;
|
|
||||||
newConfig.sign = new JarSignerConf();
|
newConfig.sign = new JarSignerConf();
|
||||||
|
|
||||||
newConfig.components = new HashMap<>();
|
newConfig.components = new HashMap<>();
|
||||||
|
@ -187,6 +188,10 @@ public void init(LaunchServer.ReloadType type) {
|
||||||
protectHandler.init(server);
|
protectHandler.init(server);
|
||||||
protectHandler.checkLaunchServerLicense();
|
protectHandler.checkLaunchServerLicense();
|
||||||
}
|
}
|
||||||
|
if(sessions != null) {
|
||||||
|
sessions.init(server);
|
||||||
|
server.registerObject("sessions", sessions);
|
||||||
|
}
|
||||||
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));
|
||||||
}
|
}
|
||||||
|
@ -229,6 +234,9 @@ public void close(LaunchServer.ReloadType type) {
|
||||||
server.unregisterObject("protectHandler", protectHandler);
|
server.unregisterObject("protectHandler", protectHandler);
|
||||||
protectHandler.close();
|
protectHandler.close();
|
||||||
}
|
}
|
||||||
|
if(sessions != null) {
|
||||||
|
server.unregisterObject("sessions", sessions);
|
||||||
|
}
|
||||||
if (dao != null) {
|
if (dao != null) {
|
||||||
server.unregisterObject("dao", dao);
|
server.unregisterObject("dao", dao);
|
||||||
if (dao instanceof AutoCloseable) {
|
if (dao instanceof AutoCloseable) {
|
||||||
|
@ -260,10 +268,6 @@ public static class ExeConf {
|
||||||
public String txtProductVersion;
|
public String txtProductVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class CertificateConf {
|
|
||||||
public boolean enabled;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class JarSignerConf {
|
public static class JarSignerConf {
|
||||||
public boolean enabled = false;
|
public boolean enabled = false;
|
||||||
public String keyStore = "pathToKey";
|
public String keyStore = "pathToKey";
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
import pro.gravit.launchserver.auth.protect.ProtectHandler;
|
||||||
import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider;
|
import pro.gravit.launchserver.auth.protect.hwid.HWIDProvider;
|
||||||
import pro.gravit.launchserver.auth.provider.AuthProvider;
|
import pro.gravit.launchserver.auth.provider.AuthProvider;
|
||||||
|
import pro.gravit.launchserver.auth.session.SessionStorage;
|
||||||
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
import pro.gravit.launchserver.auth.texture.TextureProvider;
|
||||||
import pro.gravit.launchserver.components.Component;
|
import pro.gravit.launchserver.components.Component;
|
||||||
import pro.gravit.launchserver.dao.provider.DaoProvider;
|
import pro.gravit.launchserver.dao.provider.DaoProvider;
|
||||||
|
@ -41,6 +42,7 @@ public void registerAdapters(GsonBuilder builder) {
|
||||||
builder.registerTypeAdapter(AuthRequest.AuthPasswordInterface.class, new UniversalJsonAdapter<>(AuthRequest.providers));
|
builder.registerTypeAdapter(AuthRequest.AuthPasswordInterface.class, new UniversalJsonAdapter<>(AuthRequest.providers));
|
||||||
builder.registerTypeAdapter(HWIDProvider.class, new UniversalJsonAdapter<>(HWIDProvider.providers));
|
builder.registerTypeAdapter(HWIDProvider.class, new UniversalJsonAdapter<>(HWIDProvider.providers));
|
||||||
builder.registerTypeAdapter(OptionalAction.class, new UniversalJsonAdapter<>(OptionalAction.providers));
|
builder.registerTypeAdapter(OptionalAction.class, new UniversalJsonAdapter<>(OptionalAction.providers));
|
||||||
|
builder.registerTypeAdapter(SessionStorage.class, new UniversalJsonAdapter<>(SessionStorage.providers));
|
||||||
modulesManager.invokeEvent(new PreGsonPhase(builder));
|
modulesManager.invokeEvent(new PreGsonPhase(builder));
|
||||||
//ClientWebSocketService.appendTypeAdapters(builder);
|
//ClientWebSocketService.appendTypeAdapters(builder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
import pro.gravit.utils.HookSet;
|
import pro.gravit.utils.HookSet;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
@ -15,8 +16,6 @@
|
||||||
|
|
||||||
public class SessionManager implements NeedGarbageCollection {
|
public class SessionManager implements NeedGarbageCollection {
|
||||||
|
|
||||||
private final Map<UUID, Entry> clientSet = new ConcurrentHashMap<>(128);
|
|
||||||
private final Map<UUID, Set<Entry>> uuidIndex = new ConcurrentHashMap<>(32);
|
|
||||||
private final LaunchServer server;
|
private final LaunchServer server;
|
||||||
public HookSet<Client> clientRestoreHook = new HookSet<>();
|
public HookSet<Client> clientRestoreHook = new HookSet<>();
|
||||||
|
|
||||||
|
@ -27,52 +26,35 @@ public SessionManager(LaunchServer server) {
|
||||||
|
|
||||||
public boolean addClient(Client client) {
|
public boolean addClient(Client client) {
|
||||||
if(client == null || client.session == null) return false;
|
if(client == null || client.session == null) return false;
|
||||||
remove(client.session);
|
return server.config.sessions.writeSession(client.uuid, client.session, compressClient(client));
|
||||||
Entry e = new Entry(compressClient(client), client.session);
|
|
||||||
clientSet.put(client.session, e);
|
|
||||||
if(client.isAuth && client.uuid != null) {
|
|
||||||
Set<Entry> uuidSet = uuidIndex.computeIfAbsent(client.uuid, k -> ConcurrentHashMap.newKeySet());
|
|
||||||
uuidSet.add(e);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<UUID> findSessionsByUUID(UUID uuid) {
|
public Stream<UUID> findSessionsByUUID(UUID uuid) {
|
||||||
Set<Entry> set = uuidIndex.get(uuid);
|
return server.config.sessions.getSessionsFromUserUUID(uuid);
|
||||||
if(set != null) return set.stream().map((e) -> e.sessionUuid);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean removeByUUID(UUID uuid) {
|
public boolean removeByUUID(UUID uuid) {
|
||||||
Set<Entry> set = uuidIndex.get(uuid);
|
return server.config.sessions.deleteSessionsByUserUUID(uuid);
|
||||||
if(set != null) {
|
|
||||||
for(Entry e : set) {
|
|
||||||
clientSet.remove(e.sessionUuid);
|
|
||||||
}
|
|
||||||
set.clear();
|
|
||||||
uuidIndex.remove(uuid);
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public Set<UUID> getSavedUUIDs()
|
public Set<UUID> getSavedUUIDs()
|
||||||
{
|
{
|
||||||
return uuidIndex.keySet();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void clear() {
|
public void clear() {
|
||||||
clientSet.clear();
|
server.config.sessions.clear();
|
||||||
uuidIndex.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String compressClient(Client client) {
|
private byte[] compressClient(Client client) {
|
||||||
return Launcher.gsonManager.gson.toJson(client); //Compress using later
|
return Launcher.gsonManager.gson.toJson(client).getBytes(StandardCharsets.UTF_8); //Compress using later
|
||||||
}
|
}
|
||||||
|
|
||||||
private Client decompressClient(String client) {
|
private Client decompressClient(byte[] client) {
|
||||||
return Launcher.gsonManager.gson.fromJson(client, Client.class); //Compress using later
|
return Launcher.gsonManager.gson.fromJson(new String(client, StandardCharsets.UTF_8), Client.class); //Compress using later
|
||||||
}
|
}
|
||||||
private Client restoreFromString(String data) {
|
private Client restoreFromString(byte[] data) {
|
||||||
Client result = decompressClient(data);
|
Client result = decompressClient(data);
|
||||||
result.updateAuth(server);
|
result.updateAuth(server);
|
||||||
if(result.auth != null && (result.username != null)) {
|
if(result.auth != null && (result.username != null)) {
|
||||||
|
@ -87,25 +69,11 @@ private Client restoreFromString(String data) {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void garbageCollection() {
|
public void garbageCollection() {
|
||||||
long time = System.currentTimeMillis();
|
|
||||||
long session_timeout = server.config.netty.performance.sessionLifetimeMs;
|
|
||||||
Set<UUID> to_delete = new HashSet<>(32);
|
|
||||||
clientSet.forEach((uuid, entry) -> {
|
|
||||||
long timestamp = entry.timestamp;
|
|
||||||
if(timestamp + session_timeout < time)
|
|
||||||
to_delete.add(uuid);
|
|
||||||
});
|
|
||||||
for(UUID session : to_delete) {
|
|
||||||
remove(session);
|
|
||||||
}
|
|
||||||
to_delete.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Client getClient(UUID session) {
|
public Client getClient(UUID session) {
|
||||||
Entry e = clientSet.get(session);
|
return restoreFromString(server.config.sessions.getSessionData(session));
|
||||||
if(e == null) return null;
|
|
||||||
return restoreFromString(e.data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -115,52 +83,27 @@ public Client getOrNewClient(UUID session) {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean remove(UUID session) {
|
public boolean remove(UUID session) {
|
||||||
Entry e =clientSet.remove(session);
|
return server.config.sessions.deleteSession(session);
|
||||||
if(e != null) {
|
|
||||||
Set<Entry> set = uuidIndex.get(session);
|
|
||||||
if(set != null) {
|
|
||||||
removeUuidFromIndexSet(set, e, session);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removeUuidFromIndexSet(Set<Entry> set, Entry e, UUID session) {
|
|
||||||
set.remove(e);
|
|
||||||
if(set.isEmpty()) {
|
|
||||||
uuidIndex.remove(session);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void removeClient(UUID session) {
|
public void removeClient(UUID session) {
|
||||||
remove(session);
|
remove(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public void updateClient(UUID session) {
|
public void updateClient(UUID session) {
|
||||||
LogHelper.warning("Using deprecated method: sessionManager.updateClient");
|
LogHelper.warning("Using deprecated method: sessionManager.updateClient");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
public Set<Client> getSessions() {
|
public Set<Client> getSessions() {
|
||||||
// TODO: removeme
|
|
||||||
LogHelper.warning("Using deprecated method: sessionManager.getSession");
|
LogHelper.warning("Using deprecated method: sessionManager.getSession");
|
||||||
return new HashSet<>();
|
return new HashSet<>();
|
||||||
}
|
}
|
||||||
|
@Deprecated
|
||||||
public void loadSessions(Set<Client> set) {
|
public void loadSessions(Set<Client> set) {
|
||||||
LogHelper.warning("Using deprecated method: sessionManager.loadSessions");
|
LogHelper.warning("Using deprecated method: sessionManager.loadSessions");
|
||||||
//clientSet.putAll(set.stream().collect(Collectors.toMap(c -> c.session, Function.identity())));
|
//clientSet.putAll(set.stream().collect(Collectors.toMap(c -> c.session, Function.identity())));
|
||||||
}
|
}
|
||||||
private static class Entry {
|
|
||||||
public String data;
|
|
||||||
public UUID sessionUuid;
|
|
||||||
public long timestamp;
|
|
||||||
|
|
||||||
public Entry(String data, UUID sessionUuid) {
|
|
||||||
this.data = data;
|
|
||||||
this.sessionUuid = sessionUuid;
|
|
||||||
this.timestamp = System.currentTimeMillis();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
2
modules
2
modules
|
@ -1 +1 @@
|
||||||
Subproject commit e990b35b4001e29793b383dfa7b179aa0b27b307
|
Subproject commit 5c4f6850bd4feeee0caff5561564b7e54bb94774
|
Loading…
Reference in a new issue