diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/hwid/HWIDHandler.java b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/hwid/HWIDHandler.java index 77ba174b..9fc786cf 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/auth/hwid/HWIDHandler.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/auth/hwid/HWIDHandler.java @@ -63,7 +63,7 @@ public void invoke(String... args) throws Exception { public abstract void ban(List hwid) throws HWIDException; public void check(HWID hwid, String username) throws HWIDException { - if (hwid.isNull()) return; + if (hwid == null || hwid.isNull()) return; check0(hwid, username); } diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java index 991a87ea..db19f4f5 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/manangers/SessionManager.java @@ -40,6 +40,11 @@ public Client getOrNewClient(long session) { return clientSet.computeIfAbsent(session, Client::new); } + public Client removeClient(long session) + { + return clientSet.remove(session); + } + public void updateClient(long session) { Client c = clientSet.get(session); diff --git a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java index e717dcb0..3c060a60 100644 --- a/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/WebSocketService.java @@ -66,6 +66,11 @@ public WebSocketService(ChannelGroup channels, LaunchServer server) { public void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client, String ip) { String request = frame.text(); WebSocketServerResponse response = gson.fromJson(request, WebSocketServerResponse.class); + if(response == null) + { + RequestEvent event= new ErrorRequestEvent("This type of request is not supported"); + sendObject(ctx, event); + } process(ctx, response, client, ip); } @@ -123,6 +128,7 @@ public static void registerResponses() { providers.register("getAvailabilityAuth", GetAvailabilityAuthResponse.class); providers.register("register", RegisterResponse.class); providers.register("setPassword", SetPasswordResponse.class); + providers.register("exit", ExitResponse.class); } public void sendObject(ChannelHandlerContext ctx, Object obj) { 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 new file mode 100644 index 00000000..07af9fff --- /dev/null +++ b/LaunchServer/src/main/java/pro/gravit/launchserver/socket/response/auth/ExitResponse.java @@ -0,0 +1,90 @@ +package pro.gravit.launchserver.socket.response.auth; + +import io.netty.channel.ChannelHandlerContext; +import pro.gravit.launcher.events.RequestEvent; +import pro.gravit.launcher.events.request.ExitRequestEvent; +import pro.gravit.launchserver.socket.Client; +import pro.gravit.launchserver.socket.handlers.WebSocketFrameHandler; +import pro.gravit.launchserver.socket.response.SimpleResponse; + +public class ExitResponse extends SimpleResponse { + public boolean exitAll; + public String username; + @Override + public String getType() { + return "exit"; + } + + @Override + public void execute(ChannelHandlerContext ctx, Client client) throws Exception { + if(username != null && ( !client.isAuth || client.permissions == null || !client.permissions.canAdmin )) + { + sendError("Permissions denied"); + return; + } + if(username == null) + { + if(client.session == 0 && exitAll) + { + sendError("Session invalid"); + return; + } + WebSocketFrameHandler handler = ctx.pipeline().get(WebSocketFrameHandler.class); + if(handler == null) + { + sendError("Exit internal error"); + return; + } + Client newClient = new Client(0); + newClient.isSecure = client.isSecure; + newClient.checkSign = client.checkSign; + handler.setClient(newClient); + if(client.session != 0) server.sessionManager.removeClient(client.session); + if(exitAll) + { + service.channels.forEach((channel) -> { + if(channel == null || channel.pipeline() == null) return; + WebSocketFrameHandler wsHandler = channel.pipeline().get(WebSocketFrameHandler.class); + if(wsHandler == null || wsHandler == handler) return; + Client chClient = wsHandler.getClient(); + if(client.isAuth && client.username != null) + { + if(!chClient.isAuth || !client.username.equals(chClient.username)) return; + } + else + { + if(chClient.session != client.session) return; + } + Client newCusClient = new Client(0); + newCusClient.isSecure = chClient.isSecure; + newCusClient.checkSign = chClient.checkSign; + wsHandler.setClient(newCusClient); + if(chClient.session != 0) server.sessionManager.removeClient(chClient.session); + ExitRequestEvent event = new ExitRequestEvent(ExitRequestEvent.ExitReason.SERVER); + event.requestUUID = RequestEvent.eventUUID; + wsHandler.service.sendObject(channel, event); + }); + } + sendResult(new ExitRequestEvent(ExitRequestEvent.ExitReason.CLIENT)); + } + else + { + service.channels.forEach((channel -> { + if(channel == null || channel.pipeline() == null) return; + WebSocketFrameHandler wsHandler = channel.pipeline().get(WebSocketFrameHandler.class); + if(wsHandler == null) return; + Client chClient = wsHandler.getClient(); + if(!chClient.isAuth || !username.equals(chClient.username)) return; + Client newCusClient = new Client(0); + newCusClient.isSecure = chClient.isSecure; + newCusClient.checkSign = chClient.checkSign; + wsHandler.setClient(newCusClient); + if(chClient.session != 0) server.sessionManager.removeClient(chClient.session); + ExitRequestEvent event = new ExitRequestEvent(ExitRequestEvent.ExitReason.SERVER); + event.requestUUID = RequestEvent.eventUUID; + wsHandler.service.sendObject(channel, event); + })); + sendResult(new ExitRequestEvent(ExitRequestEvent.ExitReason.NO_EXIT)); + } + } +} diff --git a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java index 3fa33b85..1b68a380 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java +++ b/Launcher/src/main/java/pro/gravit/launcher/LauncherEngine.java @@ -1,6 +1,5 @@ package pro.gravit.launcher; -import pro.gravit.launcher.api.SystemService; import pro.gravit.launcher.client.*; import pro.gravit.launcher.client.events.ClientEngineInitPhase; import pro.gravit.launcher.client.events.ClientExitPhase; @@ -59,7 +58,12 @@ public static void checkClass(Class clazz) throws SecurityException { public static void exitLauncher(int code) { modulesManager.invokeEvent(new ClientExitPhase(code)); - NativeJVMHalt.haltA(code); + try { + System.exit(code); + } catch (Throwable e) //Forge Security Manager? + { + NativeJVMHalt.haltA(code); + } } public static void main(String... args) throws Throwable { @@ -93,7 +97,7 @@ public static void main(String... args) throws Throwable { LogHelper.debug("Launcher started in %dms", endTime - startTime); //Request.service.close(); //FunctionalBridge.close(); - SystemService.exit(0); + LauncherEngine.exitLauncher(0); } public static void initGson(ClientModuleManager modulesManager) { diff --git a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncher.java b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncher.java index edd47cd2..42c85934 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncher.java +++ b/Launcher/src/main/java/pro/gravit/launcher/client/ClientLauncher.java @@ -301,7 +301,7 @@ private static void launch(ClientProfile profile, Params params) throws Throwabl try { mainMethod.invokeWithArguments((Object) args.toArray(new String[0])); } finally { - SystemService.exit(0); + LauncherEngine.exitLauncher(0); } } diff --git a/Launcher/src/main/java/pro/gravit/launcher/utils/NativeJVMHalt.java b/Launcher/src/main/java/pro/gravit/launcher/utils/NativeJVMHalt.java index 257808d0..7b9293ec 100644 --- a/Launcher/src/main/java/pro/gravit/launcher/utils/NativeJVMHalt.java +++ b/Launcher/src/main/java/pro/gravit/launcher/utils/NativeJVMHalt.java @@ -2,6 +2,7 @@ import pro.gravit.launcher.patches.FMLPatcher; import pro.gravit.utils.helper.JVMHelper; +import pro.gravit.utils.helper.LogHelper; import javax.swing.*; import java.awt.event.WindowEvent; @@ -22,23 +23,30 @@ private boolean aaabBooleanC_D() { } public static void haltA(int code) { + Throwable[] th = new Throwable[3]; NativeJVMHalt halt = new NativeJVMHalt(code); try { JVMHelper.RUNTIME.exit(code); - } catch (Throwable ignored) { + } catch (Throwable exitExc) { + th[0] = exitExc; try { new WindowShutdown(); - } catch (Throwable ignored1) { + } catch (Throwable windowExc) { + th[1] = windowExc; } } try { FMLPatcher.exit(code); - } catch (Throwable ignored) { + } catch (Throwable fmlExc) { + th[2] = fmlExc; + } + for(Throwable t : th) + { + if(t != null) LogHelper.error(t); } - - halt.aaabbb38C_D(); boolean a = halt.aaabBooleanC_D(); System.out.println(a); + halt.aaabbb38C_D(); } diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/ExitRequestEvent.java b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/ExitRequestEvent.java new file mode 100644 index 00000000..8916cf79 --- /dev/null +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/events/request/ExitRequestEvent.java @@ -0,0 +1,20 @@ +package pro.gravit.launcher.events.request; + +import pro.gravit.launcher.events.RequestEvent; + +public class ExitRequestEvent extends RequestEvent { + public enum ExitReason + { + SERVER, CLIENT, TIMEOUT, NO_EXIT + } + public final ExitReason reason; + + public ExitRequestEvent(ExitReason reason) { + this.reason = reason; + } + + @Override + public String getType() { + return "exit"; + } +} diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/auth/ExitRequest.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/auth/ExitRequest.java new file mode 100644 index 00000000..240c27a3 --- /dev/null +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/auth/ExitRequest.java @@ -0,0 +1,29 @@ +package pro.gravit.launcher.request.auth; + +import pro.gravit.launcher.events.request.ExitRequestEvent; +import pro.gravit.launcher.request.Request; + +public class ExitRequest extends Request { + public final boolean exitAll; + public final String username; + + public ExitRequest() { + this.exitAll = false; + this.username = null; + } + + public ExitRequest(boolean exitAll) { + this.exitAll = exitAll; + this.username = null; + } + + public ExitRequest(boolean exitAll, String username) { + this.exitAll = exitAll; + this.username = username; + } + + @Override + public String getType() { + return "exit"; + } +} diff --git a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java index 5b896a35..c6604048 100644 --- a/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java +++ b/LauncherAPI/src/main/java/pro/gravit/launcher/request/websockets/ClientWebSocketService.java @@ -107,6 +107,7 @@ public void registerResults() { results.register("setpassword", SetPasswordRequestEvent.class); results.register("notification", NotificationEvent.class); results.register("signal", SignalEvent.class); + results.register("exit", ExitRequestEvent.class); } public void waitIfNotConnected() { diff --git a/LauncherCore/src/main/java/pro/gravit/utils/UniversalJsonAdapter.java b/LauncherCore/src/main/java/pro/gravit/utils/UniversalJsonAdapter.java index 221df950..209354cb 100644 --- a/LauncherCore/src/main/java/pro/gravit/utils/UniversalJsonAdapter.java +++ b/LauncherCore/src/main/java/pro/gravit/utils/UniversalJsonAdapter.java @@ -15,24 +15,41 @@ public class UniversalJsonAdapter implements JsonSerializer, JsonDeseriali public final ProviderMap providerMap; public final String name; public final String PROP_NAME; + public final boolean printErrorIfUnknownType; public UniversalJsonAdapter(ProviderMap providerMap) { this.providerMap = providerMap; this.name = providerMap.getName(); this.PROP_NAME = "type"; + printErrorIfUnknownType = true; } public UniversalJsonAdapter(ProviderMap providerMap, String PROP_NAME) { this.providerMap = providerMap; this.name = providerMap.getName(); this.PROP_NAME = PROP_NAME; + printErrorIfUnknownType = true; + } + + public UniversalJsonAdapter(ProviderMap providerMap, String name, String PROP_NAME, boolean printErrorIfUnknownType) { + this.providerMap = providerMap; + this.name = name; + this.PROP_NAME = PROP_NAME; + this.printErrorIfUnknownType = printErrorIfUnknownType; + } + + public UniversalJsonAdapter(ProviderMap providerMap, String name, boolean printErrorIfUnknownType) { + this.providerMap = providerMap; + this.name = name; + this.PROP_NAME = "type"; + this.printErrorIfUnknownType = printErrorIfUnknownType; } public R deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { String typename = json.getAsJsonObject().getAsJsonPrimitive(PROP_NAME).getAsString(); Class cls = providerMap.getClass(typename); if (cls == null) { - LogHelper.error("%s %s not found", name, typename); + if(printErrorIfUnknownType) LogHelper.error("%s %s not found", name, typename); return null; } return context.deserialize(json, cls); @@ -48,9 +65,9 @@ public JsonElement serialize(R src, Type typeOfSrc, JsonSerializationContext con } if(classPath == null) { - LogHelper.warning("Class %s type null", src.getClass()); + if(printErrorIfUnknownType) LogHelper.warning("Class %s type null", src.getClass()); } - jo.add(PROP_NAME, new JsonPrimitive(classPath)); + else jo.add(PROP_NAME, new JsonPrimitive(classPath)); return jo; }