diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/ExitResponse.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/ExitResponse.java index 56335827..456d4a73 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/ExitResponse.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/ExitResponse.java @@ -54,7 +54,6 @@ public void execute(ChannelHandlerContext ctx, Client client) { support.clearSessionsByUser(client.getUser()); } } - sendResult(new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT)); } else { if (client.session == null && exitAll) { sendError("Session invalid"); @@ -80,8 +79,8 @@ public void execute(ChannelHandlerContext ctx, Client client) { exit(server, webSocketFrameHandler, channel, ExitRequestEvent.ExitReason.SERVER); })); } - sendResult(new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT)); } + sendResult(new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT)); } else { service.forEachActiveChannels(((channel, webSocketFrameHandler) -> { Client client1 = webSocketFrameHandler.getClient(); diff --git a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java index 55660685..a6d03cc9 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java +++ b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java @@ -187,17 +187,10 @@ public void start(String... args) throws Throwable { { LogHelper.debug("WebSocket connect closed. Try reconnect"); try { - Request.service.open(); - LogHelper.debug("Connect to %s", Launcher.getConfig().address); - } catch (Exception e) { - LogHelper.error(e); - throw new RequestException(String.format("Connect error: %s", e.getMessage() != null ? e.getMessage() : "null")); - } - try { - RestoreSessionRequest request1 = new RestoreSessionRequest(Request.getSession()); - request1.request(); + Request.reconnect(); } catch (Exception e) { LogHelper.error(e); + throw new RequestException("Connection failed", e); } }; } diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java index cb06b805..8c06feaf 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherEntryPoint.java @@ -91,7 +91,18 @@ public static void main(String[] args) throws Throwable { Launcher.profile = profile; AuthService.profile = profile; LauncherEngine.clientParams = params; - Request.setSession(params.session); + if(params.session != null) { + Request.setSession(params.session); + } else if(params.oauth != null) { + if(params.oauthExpiredTime != 0) { + Request.setOAuth(params.authId, params.oauth, params.oauthExpiredTime); + } else { + Request.setOAuth(params.authId, params.oauth); + } + if(params.extendedTokens != null) { + Request.addAllExtendedToken(params.extendedTokens); + } + } checkJVMBitsAndVersion(params.profile.getMinJavaVersion(), params.profile.getRecommendJavaVersion(), params.profile.getMaxJavaVersion(), params.profile.isWarnMissJavaVersion()); LauncherEngine.modulesManager.invokeEvent(new ClientProcessInitPhase(engine, params)); @@ -110,23 +121,15 @@ public static void main(String[] args) throws Throwable { // Start client with WatchService monitoring boolean digest = !profile.isUpdateFastCheck(); LogHelper.debug("Restore sessions"); - RestoreSessionRequest request = new RestoreSessionRequest(Request.getSession()); - request.request(); + Request.restore(); Request.service.reconnectCallback = () -> { LogHelper.debug("WebSocket connect closed. Try reconnect"); try { - Request.service.open(); - LogHelper.debug("Connect to %s", Launcher.getConfig().address); - } catch (Exception e) { - LogHelper.error(e); - throw new RequestException(String.format("Connect error: %s", e.getMessage() != null ? e.getMessage() : "null")); - } - try { - RestoreSessionRequest request1 = new RestoreSessionRequest(Request.getSession()); - request1.request(); + Request.reconnect(); } catch (Exception e) { LogHelper.error(e); + throw new RequestException("Connection failed", e); } }; if (params.profile.getClassLoaderConfig() == ClientProfile.ClassLoaderConfig.LAUNCHER) { diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java index 175e32df..cc1ab9d4 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncherProcess.java @@ -8,6 +8,7 @@ import pro.gravit.launcher.client.events.client.ClientProcessBuilderLaunchedEvent; import pro.gravit.launcher.client.events.client.ClientProcessBuilderParamsWrittedEvent; import pro.gravit.launcher.client.events.client.ClientProcessBuilderPreLaunchEvent; +import pro.gravit.launcher.events.request.AuthRequestEvent; import pro.gravit.launcher.hasher.HashedDir; import pro.gravit.launcher.profiles.ClientProfile; import pro.gravit.launcher.profiles.PlayerProfile; @@ -115,7 +116,13 @@ private void applyClientProfile() { if (params.ram > 0) { this.jvmArgs.add("-Xmx" + params.ram + 'M'); } - this.params.session = Request.getSession(); + this.params.oauth = Request.getOAuth(); + if(this.params.oauth == null) { + this.params.session = Request.getSession(); + } else { + this.params.oauthExpiredTime = Request.getTokenExpiredTime(); + this.params.extendedTokens = Request.getExtendedTokens(); + } if(this.params.profile.getRuntimeInClientConfig() != ClientProfile.RuntimeInClientConfig.NONE) { jvmModules.add("javafx.base"); @@ -258,6 +265,14 @@ public static class ClientParams { public UUID session; + public AuthRequestEvent.OAuthRequestEvent oauth; + + public String authId; + + public long oauthExpiredTime; + + public Map extendedTokens; + public transient HashedDir assetHDir; public transient HashedDir clientHDir; diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java index 4df1c875..77146c8e 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/Request.java @@ -2,15 +2,28 @@ import pro.gravit.launcher.Launcher; import pro.gravit.launcher.LauncherNetworkAPI; +import pro.gravit.launcher.events.request.AuthRequestEvent; +import pro.gravit.launcher.events.request.RefreshTokenRequestEvent; +import pro.gravit.launcher.events.request.RestoreRequestEvent; +import pro.gravit.launcher.request.auth.RefreshTokenRequest; +import pro.gravit.launcher.request.auth.RestoreRequest; +import pro.gravit.launcher.request.auth.RestoreSessionRequest; import pro.gravit.launcher.request.websockets.StdWebSocketService; import pro.gravit.launcher.request.websockets.WebSocketRequest; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; public abstract class Request implements WebSocketRequest { public static StdWebSocketService service; private static UUID session = UUID.randomUUID(); + private static AuthRequestEvent.OAuthRequestEvent oauth; + private static Map extendedTokens; + private static String authId; + private static long tokenExpiredTime; @LauncherNetworkAPI public final UUID requestUUID = UUID.randomUUID(); private transient final AtomicBoolean started = new AtomicBoolean(false); @@ -23,6 +36,93 @@ public static void setSession(UUID session) { Request.session = session; } + public static void setOAuth(String authId, AuthRequestEvent.OAuthRequestEvent event) { + oauth = event; + Request.authId = authId; + if(oauth != null && oauth.expire != 0) { + tokenExpiredTime = System.currentTimeMillis() + oauth.expire; + } else { + tokenExpiredTime = 0; + } + } + + public static AuthRequestEvent.OAuthRequestEvent getOAuth() { + return oauth; + } + + public static Map getExtendedTokens() { + if(extendedTokens != null) { + return Collections.unmodifiableMap(extendedTokens); + } else { + return null; + } + } + + public static void clearExtendedTokens() { + if(extendedTokens != null) { + extendedTokens.clear(); + } + } + + public static void addExtendedToken(String name, String token) { + if(extendedTokens == null) { + extendedTokens = new HashMap<>(); + } + extendedTokens.put(name, token); + } + + public static void addAllExtendedToken(Map map) { + if(extendedTokens == null) { + extendedTokens = new HashMap<>(); + } + extendedTokens.putAll(map); + } + + public static void setOAuth(String authId, AuthRequestEvent.OAuthRequestEvent event, long tokenExpiredTime) { + oauth = event; + Request.authId = authId; + Request.tokenExpiredTime = tokenExpiredTime; + } + + public static boolean isTokenExpired() { + if(oauth == null) return true; + if(tokenExpiredTime == 0) return false; + return System.currentTimeMillis() > tokenExpiredTime; + } + + public static long getTokenExpiredTime() { + return tokenExpiredTime; + } + + public static String getAccessToken() { + return oauth == null ? null : oauth.accessToken; + } + + public static String getRefreshToken() { + return oauth == null ? null : oauth.refreshToken; + } + + public static void reconnect() throws Exception { + service.open(); + restore(); + } + + public static void restore() throws Exception { + if(session != null) { + RestoreSessionRequest request = new RestoreSessionRequest(session); + request.request(); + } + else if(oauth != null) { + if(isTokenExpired() || oauth.accessToken == null) { + RefreshTokenRequest request = new RefreshTokenRequest(authId, oauth.refreshToken); + RefreshTokenRequestEvent event = request.request(); + setOAuth(authId, event.oauth); + } + RestoreRequest request = new RestoreRequest(authId, oauth.accessToken, extendedTokens, false); + request.request(); + } + } + public static void requestError(String message) throws RequestException { throw new RequestException(message); } diff --git a/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java b/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java index 168c6263..136a847f 100644 --- a/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java +++ b/ServerWrapper/src/main/java/pro/gravit/launcher/server/ServerWrapper.java @@ -35,12 +35,12 @@ import java.security.spec.InvalidKeySpecException; import java.util.Arrays; import java.util.HashMap; +import java.util.UUID; public class ServerWrapper extends JsonConfigurable { public static final Path modulesDir = Paths.get(System.getProperty("serverwrapper.modulesDir", "modules")); public static final Path modulesConfigDir = Paths.get(System.getProperty("serverwrapper.modulesConfigDir", "modules-config")); public static final Path configFile = Paths.get(System.getProperty("serverwrapper.configFile", "ServerWrapperConfig.json")); - public static final Path publicKeyFile = Paths.get(System.getProperty("serverwrapper.publicKeyFile", "public.key")); public static final boolean disableSetup = Boolean.parseBoolean(System.getProperty("serverwrapper.disableSetup", "false")); public static ServerWrapperModulesManager modulesManager; public static ServerWrapper wrapper; @@ -76,8 +76,28 @@ public boolean auth() { Launcher.getConfig(); AuthRequest request = new AuthRequest(config.login, config.password, config.auth_id, AuthRequest.ConnectTypes.API); AuthRequestEvent authResult = request.request(); + if(config.saveSession) { + if(authResult.oauth != null) { + Request.setOAuth(config.auth_id, authResult.oauth); + config.oauth = authResult.oauth; + config.oauthExpireTime = Request.getTokenExpiredTime(); + } else { + Request.setSession(authResult.session); + } + saveConfig(); + } permissions = authResult.permissions; playerProfile = authResult.playerProfile; + return true; + } catch (Throwable e) { + LogHelper.error(e); + if (config.stopOnError) System.exit(-1); + return false; + } + } + + public ProfilesRequestEvent getProfiles() { + try { ProfilesRequestEvent result = new ProfilesRequest().request(); for (ClientProfile p : result.profiles) { LogHelper.debug("Get profile: %s", p.getTitle()); @@ -97,32 +117,12 @@ public boolean auth() { if (profile == null) { LogHelper.warning("Not connected to ServerProfile. May be serverName incorrect?"); } - return true; + return result; } catch (Throwable e) { LogHelper.error(e); if (config.stopOnError) System.exit(-1); - return false; + return null; } - - } - - public boolean loopAuth(int count, int sleeptime) { - if (count == 0) { - while (true) { - if (auth()) return true; - } - } - for (int i = 0; i < count; ++i) { - if (auth()) return true; - try { - Thread.sleep(sleeptime); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - LogHelper.error(e); - return false; - } - } - return false; } public void run(String... args) throws Throwable { @@ -144,9 +144,24 @@ public void run(String... args) throws Throwable { if (config.env != null) Launcher.applyLauncherEnv(config.env); else Launcher.applyLauncherEnv(LauncherConfig.LauncherEnvironment.STD); if (config.logFile != null) LogHelper.addOutput(IOHelper.newWriter(Paths.get(config.logFile), true)); - if (config.syncAuth) auth(); - else - CommonHelper.newThread("Server Auth Thread", true, () -> loopAuth(config.reconnectCount, config.reconnectSleep)); + { + if(config.saveSession) { + if(config.oauth != null) { + Request.setOAuth(config.auth_id, config.oauth, config.oauthExpireTime); + } else { + Request.setSession(config.session); + } + try { + Request.restore(); + } catch (Exception e) { + LogHelper.error(e); + auth(); + } + } else { + auth(); + } + getProfiles(); + } modulesManager.invokeEvent(new ServerWrapperInitPhase(this)); String classname = (config.mainclass == null || config.mainclass.isEmpty()) ? args[0] : config.mainclass; if (classname.length() == 0) { @@ -187,14 +202,16 @@ public void run(String... args) throws Throwable { Request.service.reconnectCallback = () -> { LogHelper.debug("WebSocket connect closed. Try reconnect"); - try { - Request.service.open(); - LogHelper.debug("Connect to %s", config.address); - } catch (Exception e) { - LogHelper.error(e); - throw new RequestException(String.format("Connect error: %s", e.getMessage() != null ? e.getMessage() : "null")); + if(config.saveSession) { + try { + Request.restore(); + } catch (Exception e) { + auth(); + } + } else { + auth(); } - auth(); + getProfiles(); }; LogHelper.info("ServerWrapper: Project %s, LaunchServer address: %s. Title: %s", config.projectname, config.address, Launcher.profile != null ? Launcher.profile.getTitle() : "unknown"); LogHelper.info("Minecraft Version (for profile): %s", wrapper.profile == null ? "unknown" : wrapper.profile.getVersion().name); @@ -239,6 +256,7 @@ public Config getDefaultConfig() { newConfig.mainclass = ""; newConfig.syncAuth = true; newConfig.stopOnError = true; + newConfig.saveSession = true; newConfig.reconnectCount = 10; newConfig.reconnectSleep = 1000; newConfig.address = "ws://localhost:9274/api"; @@ -266,6 +284,10 @@ public static final class Config { public String[] args; public String password; public String auth_id = ""; + public boolean saveSession; + public AuthRequestEvent.OAuthRequestEvent oauth; + public long oauthExpireTime; + public UUID session; public LauncherConfig.LauncherEnvironment env; } diff --git a/ServerWrapper/src/main/java/pro/gravit/launcher/server/setup/ServerWrapperSetup.java b/ServerWrapper/src/main/java/pro/gravit/launcher/server/setup/ServerWrapperSetup.java index 2149894f..50fc47dd 100644 --- a/ServerWrapper/src/main/java/pro/gravit/launcher/server/setup/ServerWrapperSetup.java +++ b/ServerWrapper/src/main/java/pro/gravit/launcher/server/setup/ServerWrapperSetup.java @@ -67,7 +67,7 @@ public void run() throws IOException { wrapper.config.password = password; wrapper.config.stopOnError = false; wrapper.updateLauncherConfig(); - if (wrapper.auth()) { + if (wrapper.auth() && wrapper.getProfiles() != null) { break; } else { LogHelper.error("Auth error. Recheck account params");