mirror of
https://github.com/GravitLauncher/Launcher
synced 2025-01-03 22:30:31 +03:00
[FEATURE] SessionManager: uuidIndex
This commit is contained in:
parent
447866d001
commit
0f8f51ea97
6 changed files with 84 additions and 18 deletions
|
@ -312,6 +312,7 @@ public static class NettyPerformanceConfig {
|
||||||
public boolean usingEpoll;
|
public boolean usingEpoll;
|
||||||
public int bossThread;
|
public int bossThread;
|
||||||
public int workerThread;
|
public int workerThread;
|
||||||
|
public long sessionLifetimeMs = 24 * 60 * 60 * 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class NettyBindAddress {
|
public static class NettyBindAddress {
|
||||||
|
|
|
@ -5,19 +5,20 @@
|
||||||
import pro.gravit.launchserver.LaunchServer;
|
import pro.gravit.launchserver.LaunchServer;
|
||||||
import pro.gravit.launchserver.auth.RequiredDAO;
|
import pro.gravit.launchserver.auth.RequiredDAO;
|
||||||
import pro.gravit.launchserver.socket.Client;
|
import pro.gravit.launchserver.socket.Client;
|
||||||
|
import pro.gravit.utils.HookSet;
|
||||||
import pro.gravit.utils.helper.LogHelper;
|
import pro.gravit.utils.helper.LogHelper;
|
||||||
|
|
||||||
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;
|
||||||
import java.util.function.Function;
|
import java.util.stream.Stream;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class SessionManager implements NeedGarbageCollection {
|
public class SessionManager implements NeedGarbageCollection {
|
||||||
|
|
||||||
public static final long SESSION_TIMEOUT = 3 * 60 * 60 * 1000; // 3 часа
|
|
||||||
private final Map<UUID, Entry> clientSet = new ConcurrentHashMap<>(128);
|
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 SessionManager(LaunchServer server) {
|
public SessionManager(LaunchServer server) {
|
||||||
this.server = server;
|
this.server = server;
|
||||||
|
@ -25,11 +26,45 @@ public SessionManager(LaunchServer server) {
|
||||||
|
|
||||||
|
|
||||||
public boolean addClient(Client client) {
|
public boolean addClient(Client client) {
|
||||||
if(client == null) return false;
|
if(client == null || client.session == null) return false;
|
||||||
clientSet.put(client.session, new Entry(compressClient(client)));
|
remove(client.session);
|
||||||
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Stream<UUID> findSessionsByUUID(UUID uuid) {
|
||||||
|
Set<Entry> set = uuidIndex.get(uuid);
|
||||||
|
if(set != null) return set.stream().map((e) -> e.sessionUuid);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean removeByUUID(UUID uuid) {
|
||||||
|
Set<Entry> set = uuidIndex.get(uuid);
|
||||||
|
if(set != null) {
|
||||||
|
for(Entry e : set) {
|
||||||
|
clientSet.remove(e.sessionUuid);
|
||||||
|
}
|
||||||
|
set.clear();
|
||||||
|
uuidIndex.remove(uuid);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<UUID> getSavedUUIDs()
|
||||||
|
{
|
||||||
|
return uuidIndex.keySet();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clear() {
|
||||||
|
clientSet.clear();
|
||||||
|
uuidIndex.clear();
|
||||||
|
}
|
||||||
|
|
||||||
private String compressClient(Client client) {
|
private String compressClient(Client client) {
|
||||||
return Launcher.gsonManager.gson.toJson(client); //Compress using later
|
return Launcher.gsonManager.gson.toJson(client); //Compress using later
|
||||||
}
|
}
|
||||||
|
@ -46,16 +81,24 @@ private Client restoreFromString(String data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(result.refCount == null) result.refCount = new AtomicInteger(1);
|
if(result.refCount == null) result.refCount = new AtomicInteger(1);
|
||||||
|
clientRestoreHook.hook(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void garbageCollection() {
|
public void garbageCollection() {
|
||||||
long time = System.currentTimeMillis();
|
long time = System.currentTimeMillis();
|
||||||
clientSet.entrySet().removeIf(entry -> {
|
long session_timeout = server.config.netty.performance.sessionLifetimeMs;
|
||||||
long timestamp = entry.getValue().timestamp;
|
Set<UUID> to_delete = new HashSet<>(32);
|
||||||
return (timestamp + SESSION_TIMEOUT < time);
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,8 +114,27 @@ public Client getOrNewClient(UUID session) {
|
||||||
return client == null ? new Client(session) : client;
|
return client == null ? new Client(session) : client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean remove(UUID session) {
|
||||||
|
Entry e =clientSet.remove(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
|
||||||
public void removeClient(UUID session) {
|
public void removeClient(UUID session) {
|
||||||
clientSet.remove(session);
|
remove(session);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -92,10 +154,12 @@ public void loadSessions(Set<Client> set) {
|
||||||
}
|
}
|
||||||
private static class Entry {
|
private static class Entry {
|
||||||
public String data;
|
public String data;
|
||||||
|
public UUID sessionUuid;
|
||||||
public long timestamp;
|
public long timestamp;
|
||||||
|
|
||||||
public Entry(String data) {
|
public Entry(String data, UUID sessionUuid) {
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
this.sessionUuid = sessionUuid;
|
||||||
this.timestamp = System.currentTimeMillis();
|
this.timestamp = System.currentTimeMillis();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@ public class Client {
|
||||||
public boolean checkSign;
|
public boolean checkSign;
|
||||||
public ClientPermissions permissions;
|
public ClientPermissions permissions;
|
||||||
public String username;
|
public String username;
|
||||||
|
public UUID uuid;
|
||||||
public TrustLevel trustLevel;
|
public TrustLevel trustLevel;
|
||||||
|
|
||||||
public transient AuthProviderPair auth;
|
public transient AuthProviderPair auth;
|
||||||
|
|
|
@ -104,17 +104,17 @@ public void execute(ChannelHandlerContext ctx, Client clientData) throws Excepti
|
||||||
}
|
}
|
||||||
result.session = clientData.session;
|
result.session = clientData.session;
|
||||||
}
|
}
|
||||||
UUID uuid;
|
|
||||||
if (authType == ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context)) {
|
if (authType == ConnectTypes.CLIENT && server.config.protectHandler.allowGetAccessToken(context)) {
|
||||||
uuid = pair.handler.auth(aresult);
|
clientData.uuid = pair.handler.auth(aresult);
|
||||||
if (LogHelper.isDebugEnabled()) {
|
if (LogHelper.isDebugEnabled()) {
|
||||||
LogHelper.debug("Auth: %s accessToken %s uuid: %s", login, result.accessToken, uuid.toString());
|
LogHelper.debug("Auth: %s accessToken %s uuid: %s", login, result.accessToken, clientData.uuid.toString());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uuid = pair.handler.usernameToUUID(aresult.username);
|
clientData.uuid = pair.handler.usernameToUUID(aresult.username);
|
||||||
result.accessToken = null;
|
result.accessToken = null;
|
||||||
}
|
}
|
||||||
result.playerProfile = ProfileByUUIDResponse.getProfile(uuid, aresult.username, client, clientData.auth.textureProvider);
|
|
||||||
|
result.playerProfile = ProfileByUUIDResponse.getProfile(clientData.uuid, aresult.username, client, clientData.auth.textureProvider);
|
||||||
|
|
||||||
clientData.type = authType;
|
clientData.type = authType;
|
||||||
sendResult(result);
|
sendResult(result);
|
||||||
|
|
|
@ -23,7 +23,7 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
public static CurrentUserRequestEvent.UserInfo collectUserInfoFromClient(Client client) throws IOException {
|
public static CurrentUserRequestEvent.UserInfo collectUserInfoFromClient(Client client) throws IOException {
|
||||||
CurrentUserRequestEvent.UserInfo result = new CurrentUserRequestEvent.UserInfo();
|
CurrentUserRequestEvent.UserInfo result = new CurrentUserRequestEvent.UserInfo();
|
||||||
if (client.auth != null && client.isAuth && client.username != null) {
|
if (client.auth != null && client.isAuth && client.username != null) {
|
||||||
UUID uuid = client.auth.handler.usernameToUUID(client.username);
|
UUID uuid = client.uuid != null ? client.uuid : client.auth.handler.usernameToUUID(client.username);
|
||||||
if (uuid != null) {
|
if (uuid != null) {
|
||||||
result.playerProfile = ProfileByUUIDResponse.getProfile(uuid, client.username, client.profile == null ? null : client.profile.getTitle(), client.auth.textureProvider);
|
result.playerProfile = ProfileByUUIDResponse.getProfile(uuid, client.username, client.profile == null ? null : client.profile.getTitle(), client.auth.textureProvider);
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,7 +38,7 @@ public void execute(ChannelHandlerContext ctx, Client client) throws Exception {
|
||||||
Client newClient = new Client(null);
|
Client newClient = new Client(null);
|
||||||
newClient.checkSign = client.checkSign;
|
newClient.checkSign = client.checkSign;
|
||||||
handler.setClient(newClient);
|
handler.setClient(newClient);
|
||||||
if (client.session != null) server.sessionManager.removeClient(client.session);
|
if (client.session != null) server.sessionManager.remove(client.session);
|
||||||
if (exitAll) {
|
if (exitAll) {
|
||||||
service.forEachActiveChannels(((channel, webSocketFrameHandler) -> {
|
service.forEachActiveChannels(((channel, webSocketFrameHandler) -> {
|
||||||
Client client1 = webSocketFrameHandler.getClient();
|
Client client1 = webSocketFrameHandler.getClient();
|
||||||
|
@ -68,7 +68,7 @@ public static void exit(LaunchServer server, WebSocketFrameHandler wsHandler, Ch
|
||||||
Client newCusClient = new Client(null);
|
Client newCusClient = new Client(null);
|
||||||
newCusClient.checkSign = chClient.checkSign;
|
newCusClient.checkSign = chClient.checkSign;
|
||||||
wsHandler.setClient(newCusClient);
|
wsHandler.setClient(newCusClient);
|
||||||
if (chClient.session != null) server.sessionManager.removeClient(chClient.session);
|
if (chClient.session != null) server.sessionManager.remove(chClient.session);
|
||||||
ExitRequestEvent event = new ExitRequestEvent(reason);
|
ExitRequestEvent event = new ExitRequestEvent(reason);
|
||||||
event.requestUUID = RequestEvent.eventUUID;
|
event.requestUUID = RequestEvent.eventUUID;
|
||||||
wsHandler.service.sendObject(channel, event);
|
wsHandler.service.sendObject(channel, event);
|
||||||
|
|
Loading…
Reference in a new issue