package ru.gravit.launchserver.websocket; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import io.netty.channel.Channel; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.group.ChannelGroup; import io.netty.handler.codec.http.websocketx.TextWebSocketFrame; import ru.gravit.launcher.events.ExceptionEvent; import ru.gravit.launcher.events.RequestEvent; import ru.gravit.launcher.events.request.ErrorRequestEvent; import ru.gravit.launcher.hasher.HashedEntry; import ru.gravit.launcher.hasher.HashedEntryAdapter; import ru.gravit.launcher.request.JsonResultSerializeAdapter; import ru.gravit.launcher.request.ResultInterface; import ru.gravit.launchserver.LaunchServer; import ru.gravit.launchserver.socket.Client; import ru.gravit.launchserver.websocket.json.JsonResponseAdapter; import ru.gravit.launchserver.websocket.json.JsonResponseInterface; import ru.gravit.launchserver.websocket.json.SimpleResponse; import ru.gravit.launchserver.websocket.json.admin.AddLogListenerResponse; import ru.gravit.launchserver.websocket.json.admin.ExecCommandResponse; import ru.gravit.launchserver.websocket.json.auth.*; import ru.gravit.launchserver.websocket.json.profile.BatchProfileByUsername; import ru.gravit.launchserver.websocket.json.profile.ProfileByUUIDResponse; import ru.gravit.launchserver.websocket.json.profile.ProfileByUsername; import ru.gravit.launchserver.websocket.json.secure.GetSecureTokenResponse; import ru.gravit.launchserver.websocket.json.secure.VerifySecureTokenResponse; import ru.gravit.launchserver.websocket.json.update.LauncherResponse; import ru.gravit.launchserver.websocket.json.update.UpdateListResponse; import ru.gravit.launchserver.websocket.json.update.UpdateResponse; import ru.gravit.utils.helper.LogHelper; import java.lang.reflect.Type; import java.util.HashMap; @SuppressWarnings("rawtypes") public class WebSocketService { public final ChannelGroup channels; public WebSocketService(ChannelGroup channels, LaunchServer server, GsonBuilder gson) { this.channels = channels; this.server = server; this.gsonBuiler = gson; this.gsonBuiler.registerTypeAdapter(JsonResponseInterface.class, new JsonResponseAdapter(this)); this.gsonBuiler.registerTypeAdapter(ResultInterface.class, new JsonResultSerializeAdapter()); this.gsonBuiler.registerTypeAdapter(HashedEntry.class, new HashedEntryAdapter()); this.gson = gsonBuiler.create(); } private final LaunchServer server; private static final HashMap responses = new HashMap<>(); private final Gson gson; private final GsonBuilder gsonBuiler; void process(ChannelHandlerContext ctx, TextWebSocketFrame frame, Client client) { String request = frame.text(); JsonResponseInterface response = gson.fromJson(request, JsonResponseInterface.class); if(response instanceof SimpleResponse) { SimpleResponse simpleResponse = (SimpleResponse) response; simpleResponse.server = server; simpleResponse.service = this; simpleResponse.ctx = ctx; } try { response.execute(ctx, client); } catch (Exception e) { LogHelper.error(e); RequestEvent event; if(server.config.netty.sendExceptionEnabled) { event = new ExceptionEvent(e); } else { event = new ErrorRequestEvent("Fatal server error. Contact administrator"); } if(response instanceof SimpleResponse) { event.requestUUID = ((SimpleResponse) response).requestUUID; } sendObject(ctx, event); } } public Class getResponseClass(String type) { return responses.get(type); } public void registerResponse(String key, Class responseInterfaceClass) { responses.put(key, responseInterfaceClass); } public void registerClient(Channel channel) { channels.add(channel); } public void registerResponses() { registerResponse("auth", AuthResponse.class); registerResponse("checkServer", CheckServerResponse.class); registerResponse("joinServer", JoinServerResponse.class); registerResponse("profiles", ProfilesResponse.class); registerResponse("launcher", LauncherResponse.class); registerResponse("updateList", UpdateListResponse.class); registerResponse("cmdExec", ExecCommandResponse.class); registerResponse("setProfile", SetProfileResponse.class); registerResponse("addLogListener", AddLogListenerResponse.class); registerResponse("update", UpdateResponse.class); registerResponse("restoreSession", RestoreSessionResponse.class); registerResponse("batchProfileByUsername", BatchProfileByUsername.class); registerResponse("profileByUsername", ProfileByUsername.class); registerResponse("profileByUUID", ProfileByUUIDResponse.class); registerResponse("getSecureToken", GetSecureTokenResponse.class); registerResponse("verifySecureToken", VerifySecureTokenResponse.class); registerResponse("getAvailabilityAuth", GetAvailabilityAuthResponse.class); } public void sendObject(ChannelHandlerContext ctx, Object obj) { ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, ResultInterface.class))); } public void sendObject(ChannelHandlerContext ctx, Object obj, Type type) { ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type))); } public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj) { ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, ResultInterface.class))).addListener(ChannelFutureListener.CLOSE); } public void sendObjectAndClose(ChannelHandlerContext ctx, Object obj, Type type) { ctx.channel().writeAndFlush(new TextWebSocketFrame(gson.toJson(obj, type))).addListener(ChannelFutureListener.CLOSE); } public void sendEvent(EventResult obj) { channels.writeAndFlush(new TextWebSocketFrame(gson.toJson(obj))); } public static class EventResult implements ResultInterface { public EventResult() { } @Override public String getType() { return "event"; } } }